From 21739ee96391488c004995be2599fac4ef10396a Mon Sep 17 00:00:00 2001 From: Bhargav Date: Thu, 7 May 2026 10:46:33 +0200 Subject: [PATCH 001/159] added rules inspired form URD --- certora/confs/OfferTreeWellFormed.conf | 20 +++++ certora/confs/TakeCorrectness.conf | 21 +++++ certora/helpers/OfferTree.sol | 110 +++++++++++++++++++++++++ certora/specs/OfferTreeWellFormed.spec | 24 ++++++ certora/specs/TakeCorrectness.spec | 78 ++++++++++++++++++ 5 files changed, 253 insertions(+) create mode 100644 certora/confs/OfferTreeWellFormed.conf create mode 100644 certora/confs/TakeCorrectness.conf create mode 100644 certora/helpers/OfferTree.sol create mode 100644 certora/specs/OfferTreeWellFormed.spec create mode 100644 certora/specs/TakeCorrectness.spec diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf new file mode 100644 index 000000000..d88336857 --- /dev/null +++ b/certora/confs/OfferTreeWellFormed.conf @@ -0,0 +1,20 @@ +{ + "files": [ + "certora/helpers/OfferTree.sol" + ], + "verify": "OfferTree:certora/specs/OfferTreeWellFormed.spec", + "solc": "solc-0.8.34", + "solc_via_ir": true, + "solc_evm_version": "osaka", + "optimistic_loop": true, + "loop_iter": 3, + "optimistic_hashing": true, + "hashing_length_bound": 1024, + "rule_sanity": "basic", + "smt_timeout": 7200, + "prover_args": [ + "-splitParallel true", + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" + ], + "msg": "OfferTreeWellFormed" +} diff --git a/certora/confs/TakeCorrectness.conf b/certora/confs/TakeCorrectness.conf new file mode 100644 index 000000000..bbb860179 --- /dev/null +++ b/certora/confs/TakeCorrectness.conf @@ -0,0 +1,21 @@ +{ + "files": [ + "src/Midnight.sol", + "certora/helpers/OfferTree.sol" + ], + "verify": "Midnight:certora/specs/TakeCorrectness.spec", + "solc": "solc-0.8.34", + "solc_via_ir": true, + "solc_evm_version": "osaka", + "optimistic_loop": true, + "loop_iter": 3, + "optimistic_hashing": true, + "hashing_length_bound": 1024, + "rule_sanity": "basic", + "smt_timeout": 7200, + "prover_args": [ + "-splitParallel true", + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" + ], + "msg": "TakeCorrectness" +} diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol new file mode 100644 index 000000000..98e2df7d1 --- /dev/null +++ b/certora/helpers/OfferTree.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association +pragma solidity ^0.8.0; + +import {Offer} from "../../src/interfaces/IMidnight.sol"; +import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; + +/// @dev Ghost offer-tree helper used by Certora specs. +/// @dev Trees are built only via `newLeaf` and `newInternalNode`, which preserve the +/// well-formedness invariant by construction. The verified invariant is then used +/// to prove that any successful `take` against a Midnight signed root corresponds +/// to a leaf actually present in the maker's tree. +contract OfferTree { + struct Node { + bytes32 left; + bytes32 right; + bytes32 hashNode; + bool isLeaf; + } + + mapping(bytes32 => Node) internal tree; + + function newLeaf(Offer memory offer) public { + bytes32 h = UtilsLib.hashOffer(offer); + require(h != 0, "zero leaf hash"); + Node storage n = tree[h]; + require(_isEmpty(n), "leaf already populated"); + n.hashNode = h; + n.isLeaf = true; + } + + function newInternalNode(bytes32 id, bytes32 left, bytes32 right) public { + require(id != 0, "zero id"); + Node storage n = tree[id]; + require(_isEmpty(n), "node already populated"); + Node storage L = tree[left]; + Node storage R = tree[right]; + require(!_isEmpty(L), "left empty"); + require(!_isEmpty(R), "right empty"); + require(L.hashNode <= R.hashNode, "children not pair-sorted"); + n.left = left; + n.right = right; + n.hashNode = UtilsLib.commutativeHash(L.hashNode, R.hashNode); + } + + function _isEmpty(Node storage n) internal view returns (bool) { + return n.left == 0 && n.right == 0 && n.hashNode == 0 && !n.isLeaf; + } + + function isEmpty(bytes32 id) public view returns (bool) { + return _isEmpty(tree[id]); + } + + function getHash(bytes32 id) public view returns (bytes32) { + return tree[id].hashNode; + } + + function isLeafNode(bytes32 id) public view returns (bool) { + return tree[id].isLeaf; + } + + function getLeft(bytes32 id) public view returns (bytes32) { + return tree[id].left; + } + + function getRight(bytes32 id) public view returns (bytes32) { + return tree[id].right; + } + + function hashOffer(Offer memory offer) external pure returns (bytes32) { + return UtilsLib.hashOffer(offer); + } + + /// @dev Well-formed predicate. + /// @dev Empty nodes well-formed; leaves have id == hashNode and no children; + /// internal nodes have non-empty children, pair-sorted hashes, and + /// hashNode = commutativeHash(left.hashNode, right.hashNode). + function isWellFormed(bytes32 id) public view returns (bool) { + Node storage n = tree[id]; + if (_isEmpty(n)) return true; + if (n.isLeaf) { + return n.left == 0 && n.right == 0 && n.hashNode == id && n.hashNode != 0; + } else { + if (n.left == 0 || n.right == 0) return false; + Node storage L = tree[n.left]; + Node storage R = tree[n.right]; + return !_isEmpty(L) && !_isEmpty(R) && L.hashNode <= R.hashNode + && n.hashNode == UtilsLib.commutativeHash(L.hashNode, R.hashNode); + } + } + + /// @dev Walks down the tree from `id`, consuming `proof` from end to start, + /// asserting every visited node is well-formed. + /// @dev At each step, descends into the child whose hash differs from the sibling + /// hash supplied in the proof. Mirrors the upward fold in `UtilsLib.isLeaf`. + function wellFormedPath(bytes32 id, bytes32[] memory proof) public view { + for (uint256 i = proof.length;;) { + require(isWellFormed(id)); + + if (i == 0) break; + + bytes32 sibling = proof[--i]; + + bytes32 left = tree[id].left; + bytes32 right = tree[id].right; + + id = getHash(left) == sibling ? right : left; + } + } +} diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec new file mode 100644 index 000000000..f9bcef713 --- /dev/null +++ b/certora/specs/OfferTreeWellFormed.spec @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association + +// Rule A — Well-formed offer-tree invariant. +// +// Verifies that the helper's only mutators (`newLeaf`, `newInternalNode`) +// preserve `isWellFormed` for every node id. This justifies using the helper +// as a ghost tree to reason about Midnight's runtime merkle verification. + +methods { + function isEmpty(bytes32) external returns (bool) envfree; + function isWellFormed(bytes32) external returns (bool) envfree; +} + +invariant zeroIsEmpty() + isEmpty(to_bytes32(0)); + +invariant wellFormed(bytes32 id) + isWellFormed(id) + { + preserved { + requireInvariant zeroIsEmpty(); + } + } diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec new file mode 100644 index 000000000..a17a7d9a8 --- /dev/null +++ b/certora/specs/TakeCorrectness.spec @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association + +// Rule B — Take correctness against the ghost offer-tree. +// +// Statement: if the maker's signed root corresponds to a node `node` of a +// well-formed ghost offer-tree, and the supplied proof descends through +// well-formed nodes from `node`, then any successful `take` against +// `(offer, root, proof)` implies `hashOffer(offer)` is registered as a +// leaf in the ghost tree (i.e. the offer was actually committed by the +// maker, not forged via second-preimage). +// +// The well-formed invariant on the ghost tree is established by Rule A +// (see OfferTreeWellFormed.spec). + +using OfferTree as OfferTree; + +methods { + function OfferTree.getHash(bytes32) external returns (bytes32) envfree; + function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; + function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; + function OfferTree.wellFormedPath(bytes32, bytes32[]) external envfree; + function OfferTree.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + + // Real semantics required for hashOffer / isLeaf / commutativeHash: + // these are the functions whose interaction with the ghost tree we are + // verifying. Do NOT summarize. + + // Summarize internals irrelevant to the merkle/hash linkage. + function multicall(bytes[]) external => HAVOC_ALL DELETE; + + function _.price() external => NONDET; + function _.onRatify(Midnight.Offer, bytes32, bytes) external => NONDET; + function _.onBuy(bytes32, Midnight.Obligation, address, uint256, uint256, bytes) external => NONDET; + function _.onSell(bytes32, Midnight.Obligation, address, uint256, uint256, bytes) external => NONDET; + function _.transferFrom(address, address, uint256) external => NONDET; + function _.transfer(address, uint256) external => NONDET; + + function IdLib.toId(Midnight.Obligation memory, uint256, address) internal returns (bytes32) => NONDET; + function UtilsLib.mulDivDown(uint256, uint256, uint256) internal returns (uint256) => NONDET; + function UtilsLib.mulDivUp(uint256, uint256, uint256) internal returns (uint256) => NONDET; + function UtilsLib.msb(uint128) internal returns (uint256) => NONDET; + function UtilsLib.countBits(uint128) internal returns (uint256) => NONDET; + function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; + function Midnight.isHealthy(Midnight.Obligation memory, bytes32, address) internal returns (bool) => NONDET; + function Midnight.tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; +} + +/// Marquee rule: a successful take implies the offer's hash is a leaf of the +/// well-formed ghost tree pointed to by `root`. +rule takeCorrectness( + env e, + uint256 units, + address taker, + address takerCallback, + bytes takerCallbackData, + address receiverIfTakerIsSeller, + Midnight.Offer offer, + bytes ratifierData, + bytes32 root, + bytes32[] proof +) { + bytes32 node; + + // Root is the hash of some node in the ghost tree. + require OfferTree.getHash(node) == root; + require root != to_bytes32(0); + + // The proof descends through well-formed nodes from that node. + OfferTree.wellFormedPath(node, proof); + + take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData, root, proof); + + // The offer's hash is registered as a leaf in the ghost tree. + bytes32 leafId = OfferTree.hashOffer(offer); + assert OfferTree.isLeafNode(leafId); + assert OfferTree.getHash(leafId) == leafId; +} From 030c17544ea2c3642d1b94cad2866a5aad10f601 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Thu, 7 May 2026 15:31:01 +0200 Subject: [PATCH 002/159] tuned --- certora/confs/TakeCorrectness.conf | 3 +- certora/helpers/OfferTree.sol | 34 +++++++++++++------ certora/helpers/Utils.sol | 4 +++ certora/specs/TakeCorrectness.spec | 54 +++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/certora/confs/TakeCorrectness.conf b/certora/confs/TakeCorrectness.conf index bbb860179..13e5f2ff9 100644 --- a/certora/confs/TakeCorrectness.conf +++ b/certora/confs/TakeCorrectness.conf @@ -1,7 +1,8 @@ { "files": [ "src/Midnight.sol", - "certora/helpers/OfferTree.sol" + "certora/helpers/OfferTree.sol", + "certora/helpers/Utils.sol" ], "verify": "Midnight:certora/specs/TakeCorrectness.spec", "solc": "solc-0.8.34", diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 98e2df7d1..1b08014d3 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -2,7 +2,6 @@ // Copyright (c) 2025 Morpho Association pragma solidity ^0.8.0; -import {Offer} from "../../src/interfaces/IMidnight.sol"; import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; /// @dev Ghost offer-tree helper used by Certora specs. @@ -10,6 +9,10 @@ import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; /// well-formedness invariant by construction. The verified invariant is then used /// to prove that any successful `take` against a Midnight signed root corresponds /// to a leaf actually present in the maker's tree. +/// @dev Purely structural: the helper does not encode the Offer struct itself, so it +/// avoids triggering pointer-analysis failures on `Offer.obligation.collateralParams[]`. +/// Specs supply leaf hashes externally (computed via the spec's chosen hashOffer +/// summary) and assert structural well-formedness here. contract OfferTree { struct Node { bytes32 left; @@ -20,12 +23,11 @@ contract OfferTree { mapping(bytes32 => Node) internal tree; - function newLeaf(Offer memory offer) public { - bytes32 h = UtilsLib.hashOffer(offer); - require(h != 0, "zero leaf hash"); - Node storage n = tree[h]; + function newLeaf(bytes32 leafHash) public { + require(leafHash != 0, "zero leaf hash"); + Node storage n = tree[leafHash]; require(_isEmpty(n), "leaf already populated"); - n.hashNode = h; + n.hashNode = leafHash; n.isLeaf = true; } @@ -67,10 +69,6 @@ contract OfferTree { return tree[id].right; } - function hashOffer(Offer memory offer) external pure returns (bytes32) { - return UtilsLib.hashOffer(offer); - } - /// @dev Well-formed predicate. /// @dev Empty nodes well-formed; leaves have id == hashNode and no children; /// internal nodes have non-empty children, pair-sorted hashes, and @@ -90,9 +88,15 @@ contract OfferTree { } /// @dev Walks down the tree from `id`, consuming `proof` from end to start, - /// asserting every visited node is well-formed. + /// asserting every visited node is well-formed AND that the path terminates + /// at a leaf. /// @dev At each step, descends into the child whose hash differs from the sibling /// hash supplied in the proof. Mirrors the upward fold in `UtilsLib.isLeaf`. + /// @dev The leaf-termination requirement encodes the assumption that `proof.length` + /// matches the actual depth from `id` to a leaf. The on-chain `take` does NOT + /// enforce this (it accepts any proof length whose folded hash equals root) — + /// the gap is intentional in the contract and is exposed by `takeCorrectness` + /// failing if this requirement is dropped. function wellFormedPath(bytes32 id, bytes32[] memory proof) public view { for (uint256 i = proof.length;;) { require(isWellFormed(id)); @@ -104,7 +108,15 @@ contract OfferTree { bytes32 left = tree[id].left; bytes32 right = tree[id].right; + // Sibling must equal exactly one of the children's hashes. Without this, + // the downward walk and the upward fold in `UtilsLib.isLeaf` can diverge + // below the root, even though they agree on the root value: the fold + // produces a synthetic intermediate hash unrelated to actual tree nodes, + // and the spec's leaf-membership conclusion would not follow. + require(getHash(left) == sibling || getHash(right) == sibling); + id = getHash(left) == sibling ? right : left; } + require(tree[id].isLeaf); } } diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index 977cccc3d..641afb193 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -12,6 +12,10 @@ contract Utils { return keccak256(abi.encode(obligation)); } + function hashOffer(Offer memory offer) external pure returns (bytes32) { + return keccak256(abi.encode(offer)); + } + function getBit(uint128 bitmap, uint256 bit) external pure returns (bool) { return bitmap & (1 << bit) != 0; } diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index a17a7d9a8..d8e2b3f54 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -12,19 +12,44 @@ // // The well-formed invariant on the ghost tree is established by Rule A // (see OfferTreeWellFormed.spec). +// +// `UtilsLib.hashOffer` is summarized to `Utils.hashOffer`, which uses +// `keccak256(abi.encode(offer))`. This deviates from the contract's actual +// EIP-712 encoding but is sound for this rule because: +// 1. determinism is preserved across the contract call inside `take` and +// the helper-side leaf hash; +// 2. injectivity assumed via `optimistic_hashing`; +// 3. the rule reasons about the hash purely as an opaque commitment — +// its specific bit pattern doesn't matter, only that it is the same +// function on both sides. using OfferTree as OfferTree; +using Utils as Utils; methods { function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; function OfferTree.wellFormedPath(bytes32, bytes32[]) external envfree; - function OfferTree.hashOffer(Midnight.Offer) external returns (bytes32) envfree; - // Real semantics required for hashOffer / isLeaf / commutativeHash: - // these are the functions whose interaction with the ghost tree we are - // verifying. Do NOT summarize. + function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + + // Deterministic summary of UtilsLib.hashOffer so the contract and the spec + // agree on the leaf-hash function. Unsummarized, the via-ir lowering of the + // nested Offer.obligation.collateralParams[] loop blocks the prover's + // pointer/memory analysis. + function UtilsLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => + summaryHashOffer(offer); + + // Deterministic + symmetric + injective summary of UtilsLib.commutativeHash. + // The function uses inline assembly which the prover treats as a black box + // without injectivity, allowing CEXes where the upward fold (in `take`) + // and the downward walk (in `wellFormedPath`) produce the same root from + // structurally distinct intermediate hashes. The ghost axioms below enforce + // sorted-pair determinism and injectivity, matching keccak256's actual + // behavior on 64-byte inputs. + function UtilsLib.commutativeHash(bytes32 a, bytes32 b) internal returns (bytes32) => + summaryCommutativeHash(a, b); // Summarize internals irrelevant to the merkle/hash linkage. function multicall(bytes[]) external => HAVOC_ALL DELETE; @@ -42,10 +67,29 @@ methods { function UtilsLib.msb(uint128) internal returns (uint256) => NONDET; function UtilsLib.countBits(uint128) internal returns (uint256) => NONDET; function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; + function TickLib.wExp(int256) internal returns (uint256) => NONDET; function Midnight.isHealthy(Midnight.Obligation memory, bytes32, address) internal returns (bool) => NONDET; function Midnight.tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; } +function summaryHashOffer(Midnight.Offer offer) returns bytes32 { + return Utils.hashOffer(offer); +} + +persistent ghost ghostCommutativeHash(bytes32, bytes32) returns bytes32 { + // Symmetric in its arguments. + axiom forall bytes32 a. forall bytes32 b. + ghostCommutativeHash(a, b) == ghostCommutativeHash(b, a); + // Injective on unordered pairs: equal hashes imply equal unordered inputs. + axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. + ghostCommutativeHash(a1, b1) == ghostCommutativeHash(a2, b2) + => ((a1 == a2 && b1 == b2) || (a1 == b2 && b1 == a2)); +} + +function summaryCommutativeHash(bytes32 a, bytes32 b) returns bytes32 { + return ghostCommutativeHash(a, b); +} + /// Marquee rule: a successful take implies the offer's hash is a leaf of the /// well-formed ghost tree pointed to by `root`. rule takeCorrectness( @@ -72,7 +116,7 @@ rule takeCorrectness( take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData, root, proof); // The offer's hash is registered as a leaf in the ghost tree. - bytes32 leafId = OfferTree.hashOffer(offer); + bytes32 leafId = Utils.hashOffer(offer); assert OfferTree.isLeafNode(leafId); assert OfferTree.getHash(leafId) == leafId; } From 4898d7200af5c9dbaf3037ed6fc7574b1d5903f1 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 17:10:23 +0200 Subject: [PATCH 003/159] take correctness passes; added some diagnostic tests --- certora/helpers/OfferTree.sol | 65 ++++++---- certora/helpers/Utils.sol | 9 ++ certora/specs/TakeCorrectness.spec | 185 ++++++++++++++++++----------- 3 files changed, 168 insertions(+), 91 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 1b08014d3..25a2b6103 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -2,17 +2,20 @@ // Copyright (c) 2025 Morpho Association pragma solidity ^0.8.0; -import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; +import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; /// @dev Ghost offer-tree helper used by Certora specs. /// @dev Trees are built only via `newLeaf` and `newInternalNode`, which preserve the /// well-formedness invariant by construction. The verified invariant is then used -/// to prove that any successful `take` against a Midnight signed root corresponds -/// to a leaf actually present in the maker's tree. +/// to prove that any successful merkle proof verification against a Midnight +/// ratified root corresponds to a leaf actually present in the maker's tree. /// @dev Purely structural: the helper does not encode the Offer struct itself, so it -/// avoids triggering pointer-analysis failures on `Offer.obligation.collateralParams[]`. +/// avoids triggering pointer-analysis failures on `Offer.market.collateralParams[]`. /// Specs supply leaf hashes externally (computed via the spec's chosen hashOffer /// summary) and assert structural well-formedness here. +/// @dev Mirrors the post-merge `HashLib.isLeaf` proof scheme: internal nodes have +/// directional left/right children combined via `HashLib.hashNode`, and the +/// downward walk in `wellFormedPath` follows the bits of `leafIndex`. contract OfferTree { struct Node { bytes32 left; @@ -39,10 +42,9 @@ contract OfferTree { Node storage R = tree[right]; require(!_isEmpty(L), "left empty"); require(!_isEmpty(R), "right empty"); - require(L.hashNode <= R.hashNode, "children not pair-sorted"); n.left = left; n.right = right; - n.hashNode = UtilsLib.commutativeHash(L.hashNode, R.hashNode); + n.hashNode = HashLib.hashNode(L.hashNode, R.hashNode); } function _isEmpty(Node storage n) internal view returns (bool) { @@ -71,8 +73,7 @@ contract OfferTree { /// @dev Well-formed predicate. /// @dev Empty nodes well-formed; leaves have id == hashNode and no children; - /// internal nodes have non-empty children, pair-sorted hashes, and - /// hashNode = commutativeHash(left.hashNode, right.hashNode). + /// internal nodes have non-empty children and hashNode = hashNode(left.hashNode, right.hashNode). function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; @@ -82,40 +83,58 @@ contract OfferTree { if (n.left == 0 || n.right == 0) return false; Node storage L = tree[n.left]; Node storage R = tree[n.right]; - return !_isEmpty(L) && !_isEmpty(R) && L.hashNode <= R.hashNode - && n.hashNode == UtilsLib.commutativeHash(L.hashNode, R.hashNode); + return !_isEmpty(L) && !_isEmpty(R) + && n.hashNode == HashLib.hashNode(L.hashNode, R.hashNode); } } /// @dev Walks down the tree from `id`, consuming `proof` from end to start, /// asserting every visited node is well-formed AND that the path terminates /// at a leaf. - /// @dev At each step, descends into the child whose hash differs from the sibling - /// hash supplied in the proof. Mirrors the upward fold in `UtilsLib.isLeaf`. + /// @dev At each level, the bit of `leafIndex` decides which side the leaf descends to, + /// mirroring the upward fold in `HashLib.isLeaf`: + /// bit == 0 ⇒ leaf was on the LEFT (sibling is the right child). + /// bit == 1 ⇒ leaf was on the RIGHT (sibling is the left child). /// @dev The leaf-termination requirement encodes the assumption that `proof.length` - /// matches the actual depth from `id` to a leaf. The on-chain `take` does NOT - /// enforce this (it accepts any proof length whose folded hash equals root) — + /// matches the actual depth from `id` to a leaf. The on-chain `HashLib.isLeaf` does + /// NOT enforce this (it accepts any proof length whose folded hash equals root) — /// the gap is intentional in the contract and is exposed by `takeCorrectness` /// failing if this requirement is dropped. - function wellFormedPath(bytes32 id, bytes32[] memory proof) public view { + function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view { + require(leafIndex >> proof.length == 0, "leaf index out of range"); for (uint256 i = proof.length;;) { require(isWellFormed(id)); if (i == 0) break; + // If we still have proof elements to consume, the current node must be an + // internal node, not a leaf. Without this, the prover can pick a leaf as the + // starting node — `isWellFormed` accepts it via the leaf branch, the loop + // walks off the leaf's zero children into the unrelated `tree[0]` entry, and + // the well-formedness chain that should pin `hashOffer(offer)` to a leaf in + // this subtree is never established, since the leaf branch of `isWellFormed` + // generates no `hashNode(L.hashNode, R.hashNode)` equation tying the root + // hash to the merkle fold. + require(!tree[id].isLeaf); + bytes32 sibling = proof[--i]; bytes32 left = tree[id].left; bytes32 right = tree[id].right; - // Sibling must equal exactly one of the children's hashes. Without this, - // the downward walk and the upward fold in `UtilsLib.isLeaf` can diverge - // below the root, even though they agree on the root value: the fold - // produces a synthetic intermediate hash unrelated to actual tree nodes, - // and the spec's leaf-membership conclusion would not follow. - require(getHash(left) == sibling || getHash(right) == sibling); - - id = getHash(left) == sibling ? right : left; + // The sibling supplied by the proof must equal the corresponding child's + // stored hash. Without this, the downward walk and the upward fold in + // `HashLib.isLeaf` can diverge below the root, even though they agree on + // the root value: the fold produces a synthetic intermediate hash unrelated + // to actual tree nodes, and the spec's leaf-membership conclusion would not + // follow. + if ((leafIndex >> i) & 1 == 0) { + require(getHash(right) == sibling); + id = left; + } else { + require(getHash(left) == sibling); + id = right; + } } require(tree[id].isLeaf); } diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index c66abb9c9..c8dabebcf 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import {Offer, Market} from "../../src/interfaces/IMidnight.sol"; import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; +import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; import { CALLBACK_SUCCESS, LIQUIDATION_CURSOR_LOW, @@ -21,6 +22,14 @@ contract Utils { return keccak256(abi.encode(offer)); } + function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) + external + pure + returns (bool) + { + return HashLib.isLeaf(root, leafHash, leafIndex, proof); + } + function getBit(uint128 bitmap, uint256 bit) external pure returns (bool) { return bitmap & (1 << bit) != 0; } diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index d8e2b3f54..f5b39d208 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -3,21 +3,30 @@ // Rule B — Take correctness against the ghost offer-tree. // -// Statement: if the maker's signed root corresponds to a node `node` of a -// well-formed ghost offer-tree, and the supplied proof descends through -// well-formed nodes from `node`, then any successful `take` against -// `(offer, root, proof)` implies `hashOffer(offer)` is registered as a -// leaf in the ghost tree (i.e. the offer was actually committed by the -// maker, not forged via second-preimage). +// Statement: if a maker-ratified root corresponds to a node `node` of a +// well-formed ghost offer-tree, and the supplied `(leafIndex, proof)` descends +// through well-formed nodes from `node`, then a successful merkle proof +// verification (`HashLib.isLeaf`) of `hashOffer(offer)` against that root +// implies the offer is registered as a leaf in the ghost tree (i.e. the offer +// was actually committed by the maker, not forged via second-preimage). // // The well-formed invariant on the ghost tree is established by Rule A // (see OfferTreeWellFormed.spec). // -// `UtilsLib.hashOffer` is summarized to `Utils.hashOffer`, which uses +// Architectural note (post-main merge): the merkle proof verification has +// moved out of `Midnight.take` and into the ratifier contracts +// (SetterRatifier / EcrecoverRatifier), which call `HashLib.isLeaf` after +// abi-decoding `(root, leafIndex, proof)` from `ratifierData`. The chain +// `successful take ⇒ successful isRatified` is established by +// Ratification.spec (takeRequiresMakerConsent); this rule covers the remaining +// link `successful isLeaf ⇒ leaf in tree`. Composed, the original +// take-level statement still holds. +// +// `HashLib.hashOffer` is summarized to `Utils.hashOffer`, which uses // `keccak256(abi.encode(offer))`. This deviates from the contract's actual // EIP-712 encoding but is sound for this rule because: -// 1. determinism is preserved across the contract call inside `take` and -// the helper-side leaf hash; +// 1. determinism is preserved across the merkle verification and the +// helper-side leaf hash; // 2. injectivity assumed via `optimistic_hashing`; // 3. the rule reasons about the hash purely as an opaque commitment — // its specific bit pattern doesn't matter, only that it is the same @@ -30,80 +39,107 @@ methods { function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; - function OfferTree.wellFormedPath(bytes32, bytes32[]) external envfree; + function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - // Deterministic summary of UtilsLib.hashOffer so the contract and the spec - // agree on the leaf-hash function. Unsummarized, the via-ir lowering of the - // nested Offer.obligation.collateralParams[] loop blocks the prover's + // Deterministic summary of HashLib.hashOffer so the merkle verification + // (via Utils.isLeaf → HashLib.isLeaf → HashLib.hashNode) and the helper-side + // leaf hash agree on the leaf-hash function. Unsummarized, the via-ir lowering + // of the nested Offer.market.collateralParams[] loop blocks the prover's // pointer/memory analysis. - function UtilsLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => + function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - // Deterministic + symmetric + injective summary of UtilsLib.commutativeHash. - // The function uses inline assembly which the prover treats as a black box - // without injectivity, allowing CEXes where the upward fold (in `take`) - // and the downward walk (in `wellFormedPath`) produce the same root from - // structurally distinct intermediate hashes. The ghost axioms below enforce - // sorted-pair determinism and injectivity, matching keccak256's actual - // behavior on 64-byte inputs. - function UtilsLib.commutativeHash(bytes32 a, bytes32 b) internal returns (bytes32) => - summaryCommutativeHash(a, b); - - // Summarize internals irrelevant to the merkle/hash linkage. - function multicall(bytes[]) external => HAVOC_ALL DELETE; - - function _.price() external => NONDET; - function _.onRatify(Midnight.Offer, bytes32, bytes) external => NONDET; - function _.onBuy(bytes32, Midnight.Obligation, address, uint256, uint256, bytes) external => NONDET; - function _.onSell(bytes32, Midnight.Obligation, address, uint256, uint256, bytes) external => NONDET; - function _.transferFrom(address, address, uint256) external => NONDET; - function _.transfer(address, uint256) external => NONDET; - - function IdLib.toId(Midnight.Obligation memory, uint256, address) internal returns (bytes32) => NONDET; - function UtilsLib.mulDivDown(uint256, uint256, uint256) internal returns (uint256) => NONDET; - function UtilsLib.mulDivUp(uint256, uint256, uint256) internal returns (uint256) => NONDET; - function UtilsLib.msb(uint128) internal returns (uint256) => NONDET; - function UtilsLib.countBits(uint128) internal returns (uint256) => NONDET; - function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; - function TickLib.wExp(int256) internal returns (uint256) => NONDET; - function Midnight.isHealthy(Midnight.Obligation memory, bytes32, address) internal returns (bool) => NONDET; - function Midnight.tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; + // Deterministic + injective summary of HashLib.hashNode. The function uses + // inline assembly which the prover treats as a black box without injectivity, + // allowing CEXes where the upward fold (in `HashLib.isLeaf`) and the downward + // walk (in `wellFormedPath`) produce the same root from structurally distinct + // intermediate hashes. The ghost axiom below enforces ordered-pair injectivity, + // matching keccak256's actual behavior on 64-byte inputs. + function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => + summaryHashNode(a, b); } function summaryHashOffer(Midnight.Offer offer) returns bytes32 { return Utils.hashOffer(offer); } -persistent ghost ghostCommutativeHash(bytes32, bytes32) returns bytes32 { - // Symmetric in its arguments. - axiom forall bytes32 a. forall bytes32 b. - ghostCommutativeHash(a, b) == ghostCommutativeHash(b, a); - // Injective on unordered pairs: equal hashes imply equal unordered inputs. +persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { + // Injective on ordered pairs: equal hashes imply equal ordered inputs. axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. - ghostCommutativeHash(a1, b1) == ghostCommutativeHash(a2, b2) - => ((a1 == a2 && b1 == b2) || (a1 == b2 && b1 == a2)); + ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); +} + +function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { + return ghostHashNode(a, b); +} + +// --------------------------------------------------------------------------- +// Diagnostic rules — isolate whether Z3 can use the implication-form +// injectivity axiom on `ghostHashNode`. They do not exercise storage, +// `wellFormedPath`, or `hashOffer`; they only put `ghostHashNode` applications +// in front of the solver and ask it to derive the consequent of the axiom. +// +// If `diagInjectivityOneStep` fails: the axiom is unusable even at one level. +// If `diagInjectivityOneStep` passes but `diagInjectivityTwoStep` fails: the +// solver instantiates the axiom for ground arguments but does not chain +// through a compound `ghostHashNode(...)` sub-term — which is the chain +// structure `takeCorrectness` requires. +// --------------------------------------------------------------------------- + +rule diagInjectivityOneStep(bytes32 a1, bytes32 b1, bytes32 a2, bytes32 b2) { + require ghostHashNode(a1, b1) == ghostHashNode(a2, b2); + assert a1 == a2; + assert b1 == b2; } -function summaryCommutativeHash(bytes32 a, bytes32 b) returns bytes32 { - return ghostCommutativeHash(a, b); +rule diagInjectivityTwoStep(bytes32 sib0, bytes32 sib1, bytes32 leaf1, bytes32 leaf2) { + require ghostHashNode(ghostHashNode(sib0, leaf1), sib1) + == ghostHashNode(ghostHashNode(sib0, leaf2), sib1); + assert leaf1 == leaf2; } -/// Marquee rule: a successful take implies the offer's hash is a leaf of the -/// well-formed ghost tree pointed to by `root`. -rule takeCorrectness( - env e, - uint256 units, - address taker, - address takerCallback, - bytes takerCallbackData, - address receiverIfTakerIsSeller, - Midnight.Offer offer, - bytes ratifierData, +// Tests pure EUF substitution: combine an equation about a storage-derived +// `intermediate` with an equation about `ghostHashNode` applications, and ask +// Z3 to apply two-step injectivity through the substitution. If this passes, +// the SMT layer handles the substitution and the `takeCorrectness` bug must +// be in how `wellFormedPath` establishes its constraints (or in storage +// aliasing across the `wellFormedPath`/`Utils.isLeaf` boundary). If it fails, +// the axiom shape itself can't close this chain even when stated as plain +// SMT facts, and the axiom needs strengthening. +rule diagSubstitution( bytes32 root, - bytes32[] proof + bytes32 sib0, + bytes32 sib1, + bytes32 D, + bytes32 leafHash, + bytes32 intermediate ) { + require ghostHashNode(intermediate, sib1) == root; + require intermediate == ghostHashNode(sib0, D); + require ghostHashNode(ghostHashNode(sib0, leafHash), sib1) == root; + assert D == leafHash; +} + +// Mirrors `takeCorrectness` but replaces the `hashOffer`-derived `leafId` with a +// free bytes32. If this passes: `hashOffer` (the offer-encoding side) is part +// of the problem. If it fails with the same shape: the failure lives entirely +// in the `wellFormedPath` + `Utils.isLeaf` composition through OfferTree +// storage, independent of how `leafHash` got there. +rule diagTakeCorrectnessFreeLeaf(bytes32 root, uint256 leafIndex, bytes32[] proof, bytes32 leafHash) { + bytes32 node; + require OfferTree.getHash(node) == root; + require root != to_bytes32(0); + OfferTree.wellFormedPath(node, leafIndex, proof); + require Utils.isLeaf(root, leafHash, leafIndex, proof); + assert OfferTree.isLeafNode(leafHash); +} + +/// Marquee rule: a successful merkle verification implies the offer's hash is a +/// leaf of the well-formed ghost tree pointed to by `root`. +rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; // Root is the hash of some node in the ghost tree. @@ -111,12 +147,25 @@ rule takeCorrectness( require root != to_bytes32(0); // The proof descends through well-formed nodes from that node. - OfferTree.wellFormedPath(node, proof); + OfferTree.wellFormedPath(node, leafIndex, proof); + + // Compute the offer's leaf hash once and reuse the symbolic value below. + // Two syntactic `Utils.hashOffer(offer)` sites would each lower to + // `keccak256(abi.encode(offer))` over freshly-materialized `bytes memory`; + // the prover's hashing model only treats keccak as injective on + // byte-equal inputs, and the `Offer.market.collateralParams[]` nested + // dynamic array (the same pointer/memory analysis limitation that + // motivates the `HashLib.hashOffer` summary above) blocks proving the + // two encoded buffers identical. The merkle-fold side and the + // assertion side could then bind to different symbolic hashes, yielding + // a spurious CEX where the upward fold pins one hash to a leaf in the + // ghost tree but the assertion reads a different hash that isn't. + bytes32 leafId = Utils.hashOffer(offer); - take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData, root, proof); + // Successful on-chain merkle verification: leafId folds up to root + // along the supplied (leafIndex, proof). + require Utils.isLeaf(root, leafId, leafIndex, proof); // The offer's hash is registered as a leaf in the ghost tree. - bytes32 leafId = Utils.hashOffer(offer); assert OfferTree.isLeafNode(leafId); - assert OfferTree.getHash(leafId) == leafId; } From 215698bc858baa8e85dda0fa754c899e91857667 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 17:12:48 +0200 Subject: [PATCH 004/159] removed the diagnostic rules --- certora/specs/TakeCorrectness.spec | 61 ------------------------------ 1 file changed, 61 deletions(-) diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index f5b39d208..0be4539a2 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -76,67 +76,6 @@ function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { return ghostHashNode(a, b); } -// --------------------------------------------------------------------------- -// Diagnostic rules — isolate whether Z3 can use the implication-form -// injectivity axiom on `ghostHashNode`. They do not exercise storage, -// `wellFormedPath`, or `hashOffer`; they only put `ghostHashNode` applications -// in front of the solver and ask it to derive the consequent of the axiom. -// -// If `diagInjectivityOneStep` fails: the axiom is unusable even at one level. -// If `diagInjectivityOneStep` passes but `diagInjectivityTwoStep` fails: the -// solver instantiates the axiom for ground arguments but does not chain -// through a compound `ghostHashNode(...)` sub-term — which is the chain -// structure `takeCorrectness` requires. -// --------------------------------------------------------------------------- - -rule diagInjectivityOneStep(bytes32 a1, bytes32 b1, bytes32 a2, bytes32 b2) { - require ghostHashNode(a1, b1) == ghostHashNode(a2, b2); - assert a1 == a2; - assert b1 == b2; -} - -rule diagInjectivityTwoStep(bytes32 sib0, bytes32 sib1, bytes32 leaf1, bytes32 leaf2) { - require ghostHashNode(ghostHashNode(sib0, leaf1), sib1) - == ghostHashNode(ghostHashNode(sib0, leaf2), sib1); - assert leaf1 == leaf2; -} - -// Tests pure EUF substitution: combine an equation about a storage-derived -// `intermediate` with an equation about `ghostHashNode` applications, and ask -// Z3 to apply two-step injectivity through the substitution. If this passes, -// the SMT layer handles the substitution and the `takeCorrectness` bug must -// be in how `wellFormedPath` establishes its constraints (or in storage -// aliasing across the `wellFormedPath`/`Utils.isLeaf` boundary). If it fails, -// the axiom shape itself can't close this chain even when stated as plain -// SMT facts, and the axiom needs strengthening. -rule diagSubstitution( - bytes32 root, - bytes32 sib0, - bytes32 sib1, - bytes32 D, - bytes32 leafHash, - bytes32 intermediate -) { - require ghostHashNode(intermediate, sib1) == root; - require intermediate == ghostHashNode(sib0, D); - require ghostHashNode(ghostHashNode(sib0, leafHash), sib1) == root; - assert D == leafHash; -} - -// Mirrors `takeCorrectness` but replaces the `hashOffer`-derived `leafId` with a -// free bytes32. If this passes: `hashOffer` (the offer-encoding side) is part -// of the problem. If it fails with the same shape: the failure lives entirely -// in the `wellFormedPath` + `Utils.isLeaf` composition through OfferTree -// storage, independent of how `leafHash` got there. -rule diagTakeCorrectnessFreeLeaf(bytes32 root, uint256 leafIndex, bytes32[] proof, bytes32 leafHash) { - bytes32 node; - require OfferTree.getHash(node) == root; - require root != to_bytes32(0); - OfferTree.wellFormedPath(node, leafIndex, proof); - require Utils.isLeaf(root, leafHash, leafIndex, proof); - assert OfferTree.isLeafNode(leafHash); -} - /// Marquee rule: a successful merkle verification implies the offer's hash is a /// leaf of the well-formed ghost tree pointed to by `root`. rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { From b62eae77790c1c3721794568b186dabecb4f562c Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 17:18:27 +0200 Subject: [PATCH 005/159] cleaned up comments --- certora/helpers/OfferTree.sol | 58 ++++++++----------------- certora/specs/TakeCorrectness.spec | 69 ++++-------------------------- 2 files changed, 25 insertions(+), 102 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 25a2b6103..25e768212 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -4,18 +4,9 @@ pragma solidity ^0.8.0; import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; -/// @dev Ghost offer-tree helper used by Certora specs. -/// @dev Trees are built only via `newLeaf` and `newInternalNode`, which preserve the -/// well-formedness invariant by construction. The verified invariant is then used -/// to prove that any successful merkle proof verification against a Midnight -/// ratified root corresponds to a leaf actually present in the maker's tree. -/// @dev Purely structural: the helper does not encode the Offer struct itself, so it -/// avoids triggering pointer-analysis failures on `Offer.market.collateralParams[]`. -/// Specs supply leaf hashes externally (computed via the spec's chosen hashOffer -/// summary) and assert structural well-formedness here. -/// @dev Mirrors the post-merge `HashLib.isLeaf` proof scheme: internal nodes have -/// directional left/right children combined via `HashLib.hashNode`, and the -/// downward walk in `wellFormedPath` follows the bits of `leafIndex`. +// Ghost offer-tree helper used by Certora specs. +// Trees are built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by construction. +// Specs supply leaf hashes externally; the helper does not encode the Offer struct itself. contract OfferTree { struct Node { bytes32 left; @@ -24,8 +15,12 @@ contract OfferTree { bool isLeaf; } + /* STORAGE */ + mapping(bytes32 => Node) internal tree; + /* MAIN FUNCTIONS */ + function newLeaf(bytes32 leafHash) public { require(leafHash != 0, "zero leaf hash"); Node storage n = tree[leafHash]; @@ -47,6 +42,8 @@ contract OfferTree { n.hashNode = HashLib.hashNode(L.hashNode, R.hashNode); } + /* PURE AND VIEW FUNCTIONS */ + function _isEmpty(Node storage n) internal view returns (bool) { return n.left == 0 && n.right == 0 && n.hashNode == 0 && !n.isLeaf; } @@ -71,9 +68,10 @@ contract OfferTree { return tree[id].right; } - /// @dev Well-formed predicate. - /// @dev Empty nodes well-formed; leaves have id == hashNode and no children; - /// internal nodes have non-empty children and hashNode = hashNode(left.hashNode, right.hashNode). + // The specification of a well-formed tree is the following: + // - empty nodes are well-formed + // - leaves have id == hashNode and no children + // - internal nodes have non-empty children and hashNode = hashNode(left.hashNode, right.hashNode) function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; @@ -88,18 +86,9 @@ contract OfferTree { } } - /// @dev Walks down the tree from `id`, consuming `proof` from end to start, - /// asserting every visited node is well-formed AND that the path terminates - /// at a leaf. - /// @dev At each level, the bit of `leafIndex` decides which side the leaf descends to, - /// mirroring the upward fold in `HashLib.isLeaf`: - /// bit == 0 ⇒ leaf was on the LEFT (sibling is the right child). - /// bit == 1 ⇒ leaf was on the RIGHT (sibling is the left child). - /// @dev The leaf-termination requirement encodes the assumption that `proof.length` - /// matches the actual depth from `id` to a leaf. The on-chain `HashLib.isLeaf` does - /// NOT enforce this (it accepts any proof length whose folded hash equals root) — - /// the gap is intentional in the contract and is exposed by `takeCorrectness` - /// failing if this requirement is dropped. + // Check that the nodes are well-formed starting from `id` and going down the `tree`. + // The bits of `leafIndex` choose the path downward; `proof` supplies the sibling hashes consumed from end to start. + // The path must terminate at a leaf, matching the depth implied by `proof.length`. function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view { require(leafIndex >> proof.length == 0, "leaf index out of range"); for (uint256 i = proof.length;;) { @@ -107,14 +96,7 @@ contract OfferTree { if (i == 0) break; - // If we still have proof elements to consume, the current node must be an - // internal node, not a leaf. Without this, the prover can pick a leaf as the - // starting node — `isWellFormed` accepts it via the leaf branch, the loop - // walks off the leaf's zero children into the unrelated `tree[0]` entry, and - // the well-formedness chain that should pin `hashOffer(offer)` to a leaf in - // this subtree is never established, since the leaf branch of `isWellFormed` - // generates no `hashNode(L.hashNode, R.hashNode)` equation tying the root - // hash to the merkle fold. + // If proof elements remain, the current node must be internal; otherwise the path walks off a leaf's zero children into the unrelated `tree[0]` entry. require(!tree[id].isLeaf); bytes32 sibling = proof[--i]; @@ -122,12 +104,6 @@ contract OfferTree { bytes32 left = tree[id].left; bytes32 right = tree[id].right; - // The sibling supplied by the proof must equal the corresponding child's - // stored hash. Without this, the downward walk and the upward fold in - // `HashLib.isLeaf` can diverge below the root, even though they agree on - // the root value: the fold produces a synthetic intermediate hash unrelated - // to actual tree nodes, and the spec's leaf-membership conclusion would not - // follow. if ((leafIndex >> i) & 1 == 0) { require(getHash(right) == sibling); id = left; diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index 0be4539a2..f0c0ce0fe 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -1,37 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2025 Morpho Association -// Rule B — Take correctness against the ghost offer-tree. -// -// Statement: if a maker-ratified root corresponds to a node `node` of a -// well-formed ghost offer-tree, and the supplied `(leafIndex, proof)` descends -// through well-formed nodes from `node`, then a successful merkle proof -// verification (`HashLib.isLeaf`) of `hashOffer(offer)` against that root -// implies the offer is registered as a leaf in the ghost tree (i.e. the offer -// was actually committed by the maker, not forged via second-preimage). -// -// The well-formed invariant on the ghost tree is established by Rule A -// (see OfferTreeWellFormed.spec). -// -// Architectural note (post-main merge): the merkle proof verification has -// moved out of `Midnight.take` and into the ratifier contracts -// (SetterRatifier / EcrecoverRatifier), which call `HashLib.isLeaf` after -// abi-decoding `(root, leafIndex, proof)` from `ratifierData`. The chain -// `successful take ⇒ successful isRatified` is established by -// Ratification.spec (takeRequiresMakerConsent); this rule covers the remaining -// link `successful isLeaf ⇒ leaf in tree`. Composed, the original -// take-level statement still holds. -// -// `HashLib.hashOffer` is summarized to `Utils.hashOffer`, which uses -// `keccak256(abi.encode(offer))`. This deviates from the contract's actual -// EIP-712 encoding but is sound for this rule because: -// 1. determinism is preserved across the merkle verification and the -// helper-side leaf hash; -// 2. injectivity assumed via `optimistic_hashing`; -// 3. the rule reasons about the hash purely as an opaque commitment — -// its specific bit pattern doesn't matter, only that it is the same -// function on both sides. - using OfferTree as OfferTree; using Utils as Utils; @@ -44,20 +13,11 @@ methods { function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - // Deterministic summary of HashLib.hashOffer so the merkle verification - // (via Utils.isLeaf → HashLib.isLeaf → HashLib.hashNode) and the helper-side - // leaf hash agree on the leaf-hash function. Unsummarized, the via-ir lowering - // of the nested Offer.market.collateralParams[] loop blocks the prover's - // pointer/memory analysis. + // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - // Deterministic + injective summary of HashLib.hashNode. The function uses - // inline assembly which the prover treats as a black box without injectivity, - // allowing CEXes where the upward fold (in `HashLib.isLeaf`) and the downward - // walk (in `wellFormedPath`) produce the same root from structurally distinct - // intermediate hashes. The ghost axiom below enforces ordered-pair injectivity, - // matching keccak256's actual behavior on 64-byte inputs. + // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); } @@ -66,8 +26,8 @@ function summaryHashOffer(Midnight.Offer offer) returns bytes32 { return Utils.hashOffer(offer); } +// Injective on ordered pairs. persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { - // Injective on ordered pairs: equal hashes imply equal ordered inputs. axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); } @@ -76,35 +36,22 @@ function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { return ghostHashNode(a, b); } -/// Marquee rule: a successful merkle verification implies the offer's hash is a -/// leaf of the well-formed ghost tree pointed to by `root`. +// The main correctness result of the verification. +// It ensures that if a maker-ratified root corresponds to a node of a well-formed offer-tree, then a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; - // Root is the hash of some node in the ghost tree. + // Assume that root is the hash of node in the tree. require OfferTree.getHash(node) == root; require root != to_bytes32(0); - // The proof descends through well-formed nodes from that node. + // Assume that the tree is well-formed along the proof path from node down to a leaf. OfferTree.wellFormedPath(node, leafIndex, proof); - // Compute the offer's leaf hash once and reuse the symbolic value below. - // Two syntactic `Utils.hashOffer(offer)` sites would each lower to - // `keccak256(abi.encode(offer))` over freshly-materialized `bytes memory`; - // the prover's hashing model only treats keccak as injective on - // byte-equal inputs, and the `Offer.market.collateralParams[]` nested - // dynamic array (the same pointer/memory analysis limitation that - // motivates the `HashLib.hashOffer` summary above) blocks proving the - // two encoded buffers identical. The merkle-fold side and the - // assertion side could then bind to different symbolic hashes, yielding - // a spurious CEX where the upward fold pins one hash to a leaf in the - // ghost tree but the assertion reads a different hash that isn't. + // Compute the leaf hash once so both uses below bind to the same symbolic value. bytes32 leafId = Utils.hashOffer(offer); - // Successful on-chain merkle verification: leafId folds up to root - // along the supplied (leafIndex, proof). require Utils.isLeaf(root, leafId, leafIndex, proof); - // The offer's hash is registered as a leaf in the ghost tree. assert OfferTree.isLeafNode(leafId); } From b9d943ea13c628c5a704ac1d9200eec27763f787 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 17:39:54 +0200 Subject: [PATCH 006/159] add completeness rule --- certora/helpers/OfferTree.sol | 4 +++- certora/specs/OfferTreeWellFormed.spec | 4 ++-- certora/specs/TakeCorrectness.spec | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 25e768212..d7cfd3e1b 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -89,7 +89,8 @@ contract OfferTree { // Check that the nodes are well-formed starting from `id` and going down the `tree`. // The bits of `leafIndex` choose the path downward; `proof` supplies the sibling hashes consumed from end to start. // The path must terminate at a leaf, matching the depth implied by `proof.length`. - function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view { + // Returns the id of the leaf at the bottom of the path. + function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bytes32) { require(leafIndex >> proof.length == 0, "leaf index out of range"); for (uint256 i = proof.length;;) { require(isWellFormed(id)); @@ -113,5 +114,6 @@ contract OfferTree { } } require(tree[id].isLeaf); + return id; } } diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index f9bcef713..f9b941425 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -12,10 +12,10 @@ methods { function isWellFormed(bytes32) external returns (bool) envfree; } -invariant zeroIsEmpty() +strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); -invariant wellFormed(bytes32 id) +strong invariant wellFormed(bytes32 id) isWellFormed(id) { preserved { diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index f0c0ce0fe..aa0665656 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -8,7 +8,7 @@ methods { function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; - function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external envfree; + function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; @@ -37,7 +37,7 @@ function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { } // The main correctness result of the verification. -// It ensures that if a maker-ratified root corresponds to a node of a well-formed offer-tree, then a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. +// If a maker-ratified root corresponds to a node of a well-formed offer-tree, then a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; @@ -55,3 +55,16 @@ rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, byte assert OfferTree.isLeafNode(leafId); } + +// The completeness dual of takeCorrectness. +// Every leaf in a well-formed offer-tree has a verifying merkle proof: folding the path's sibling hashes back up against the leaf reproduces the root. +rule takeCompleteness(bytes32 node, bytes32 root, uint256 leafIndex, bytes32[] proof) { + // Assume that root is the hash of node in the tree. + require OfferTree.getHash(node) == root; + require root != to_bytes32(0); + + // Walk the well-formed path; the call returns the leaf at the bottom. + bytes32 endLeaf = OfferTree.wellFormedPath(node, leafIndex, proof); + + assert Utils.isLeaf(root, endLeaf, leafIndex, proof); +} From 9b92e504657a15673431385a96f5d410660ea825 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 18:05:20 +0200 Subject: [PATCH 007/159] abstract properties instantiated to midnight --- certora/confs/SetterRatification.conf | 23 ++++++++++ certora/specs/SetterRatification.spec | 63 +++++++++++++++++++++++++++ certora/specs/TakeCorrectness.spec | 47 ++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 certora/confs/SetterRatification.conf create mode 100644 certora/specs/SetterRatification.spec diff --git a/certora/confs/SetterRatification.conf b/certora/confs/SetterRatification.conf new file mode 100644 index 000000000..61dea9691 --- /dev/null +++ b/certora/confs/SetterRatification.conf @@ -0,0 +1,23 @@ +{ + "files": [ + "src/Midnight.sol", + "src/ratifiers/SetterRatifier.sol", + "certora/helpers/OfferTree.sol", + "certora/helpers/Utils.sol" + ], + "verify": "Midnight:certora/specs/SetterRatification.spec", + "solc": "solc-0.8.34", + "solc_via_ir": true, + "solc_evm_version": "osaka", + "optimistic_loop": true, + "loop_iter": 3, + "optimistic_hashing": true, + "hashing_length_bound": 1024, + "rule_sanity": "basic", + "smt_timeout": 7200, + "prover_args": [ + "-splitParallel true", + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" + ], + "msg": "SetterRatification" +} diff --git a/certora/specs/SetterRatification.spec b/certora/specs/SetterRatification.spec new file mode 100644 index 000000000..ade7f3ae4 --- /dev/null +++ b/certora/specs/SetterRatification.spec @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association + +using OfferTree as OfferTree; +using Utils as Utils; +using SetterRatifier as SetterRatifier; + +methods { + function OfferTree.getHash(bytes32) external returns (bytes32) envfree; + function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; + function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; + function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; + + function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; + + function SetterRatifier.isRootRatified(address, bytes32) external returns (bool) envfree; + + // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. + function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => + summaryHashOffer(offer); + + // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. + function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => + summaryHashNode(a, b); +} + +function summaryHashOffer(Midnight.Offer offer) returns bytes32 { + return Utils.hashOffer(offer); +} + +// Injective on ordered pairs. +persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { + axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. + ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); +} + +function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { + return ghostHashNode(a, b); +} + +// SetterRatifier-specific framing of takeCorrectness. +// Premise: the maker has explicitly committed to `root` via SetterRatifier.setIsRootRatified. Conclusion: every offer whose hash verifies against `root` via merkle proof is registered as a leaf in the maker's committed offer-tree. +rule setterRatifiedTakeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { + bytes32 node; + + // Assume that the maker has explicitly committed to root via SetterRatifier. + require SetterRatifier.isRootRatified(offer.maker, root); + + // Assume that root is the hash of node in the maker's tree. + require OfferTree.getHash(node) == root; + require root != to_bytes32(0); + + // Assume that the tree is well-formed along the proof path from node down to a leaf. + OfferTree.wellFormedPath(node, leafIndex, proof); + + // Compute the leaf hash once so both uses below bind to the same symbolic value. + bytes32 leafId = Utils.hashOffer(offer); + + require Utils.isLeaf(root, leafId, leafIndex, proof); + + assert OfferTree.isLeafNode(leafId); +} diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index aa0665656..cb671fa49 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -5,6 +5,8 @@ using OfferTree as OfferTree; using Utils as Utils; methods { + function isAuthorized(address authorizer, address authorized) external returns (bool) envfree; + function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; @@ -20,6 +22,24 @@ methods { // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); + + // Take-side externals summarized as NONDET / havoc — irrelevant to the merkle-membership property. + // `isRatified` is NONDET'd so the rule abstracts over the ratifier choice: the bridge from + // `take ⇒ Utils.isLeaf success` is supplied explicitly in `takeImpliesLeafInTree` below. + function _.isRatified(Midnight.Offer, bytes) external => NONDET; + function _.onBuy(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; + function _.onSell(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; + function _.transferFrom(address, address, uint256) external => NONDET; + function _.transfer(address, uint256) external => NONDET; + function multicall(bytes[]) external => HAVOC_ALL DELETE; + function IdLib.toId(Midnight.Market memory, uint256, address) internal returns (bytes32) => NONDET; + function UtilsLib.mulDivDown(uint256, uint256, uint256) internal returns (uint256) => NONDET; + function UtilsLib.mulDivUp(uint256, uint256, uint256) internal returns (uint256) => NONDET; + function UtilsLib.msb(uint128) internal returns (uint256) => NONDET; + function UtilsLib.countBits(uint128) internal returns (uint256) => NONDET; + function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; + function isHealthy(Midnight.Market memory, bytes32, address) internal returns (bool) => NONDET; + function tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; } function summaryHashOffer(Midnight.Offer offer) returns bytes32 { @@ -68,3 +88,30 @@ rule takeCompleteness(bytes32 node, bytes32 root, uint256 leafIndex, bytes32[] p assert Utils.isLeaf(root, endLeaf, leafIndex, proof); } + +// The take-level guarantee: every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. +// The bridge from take's success to the merkle check is supplied by `require Utils.isLeaf(...)` below. It is justified by composition: take's body requires `isRatified(offer, ratifierData) == CALLBACK_SUCCESS`, and both SetterRatifier and EcrecoverRatifier implementations `require(HashLib.isLeaf(root, hashOffer(offer), leafIndex, proof))` for the (root, leafIndex, proof) they decode from ratifierData — regardless of how the maker committed the root (on-chain via `isRootRatified`, or off-chain via EIP-712 signature). +rule takeImpliesLeafInTree( + env e, + uint256 units, address taker, address takerCallback, bytes takerCallbackData, + address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, + bytes32 root, uint256 leafIndex, bytes32[] proof +) { + bytes32 node; + + // Assume that root is the hash of node in the maker's tree. + require OfferTree.getHash(node) == root; + require root != to_bytes32(0); + + // Assume that the tree is well-formed along the proof path from node down to a leaf. + OfferTree.wellFormedPath(node, leafIndex, proof); + + bytes32 leafId = Utils.hashOffer(offer); + + // Bridge: a successful take implies the chosen ratifier's `isRatified` returned CALLBACK_SUCCESS, which implies `HashLib.isLeaf(...)` passed for the (root, leafIndex, proof) it decoded from ratifierData. We model that decoded triple as the rule's (root, leafIndex, proof). + require Utils.isLeaf(root, leafId, leafIndex, proof); + + take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData); + + assert OfferTree.isLeafNode(leafId); +} From 0cd4f3eebe0d5cf7144a2a8e530e486b0813b253 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 18:07:39 +0200 Subject: [PATCH 008/159] cvl fmt --- certora/specs/SetterRatification.spec | 9 +++------ certora/specs/TakeCorrectness.spec | 16 ++++------------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/certora/specs/SetterRatification.spec b/certora/specs/SetterRatification.spec index ade7f3ae4..673ed887e 100644 --- a/certora/specs/SetterRatification.spec +++ b/certora/specs/SetterRatification.spec @@ -17,12 +17,10 @@ methods { function SetterRatifier.isRootRatified(address, bytes32) external returns (bool) envfree; // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. - function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => - summaryHashOffer(offer); + function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. - function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => - summaryHashNode(a, b); + function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); } function summaryHashOffer(Midnight.Offer offer) returns bytes32 { @@ -31,8 +29,7 @@ function summaryHashOffer(Midnight.Offer offer) returns bytes32 { // Injective on ordered pairs. persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { - axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. - ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); + axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); } function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/TakeCorrectness.spec index cb671fa49..f381cd7c8 100644 --- a/certora/specs/TakeCorrectness.spec +++ b/certora/specs/TakeCorrectness.spec @@ -16,12 +16,10 @@ methods { function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. - function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => - summaryHashOffer(offer); + function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. - function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => - summaryHashNode(a, b); + function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); // Take-side externals summarized as NONDET / havoc — irrelevant to the merkle-membership property. // `isRatified` is NONDET'd so the rule abstracts over the ratifier choice: the bridge from @@ -48,8 +46,7 @@ function summaryHashOffer(Midnight.Offer offer) returns bytes32 { // Injective on ordered pairs. persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { - axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. - ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); + axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); } function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { @@ -91,12 +88,7 @@ rule takeCompleteness(bytes32 node, bytes32 root, uint256 leafIndex, bytes32[] p // The take-level guarantee: every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. // The bridge from take's success to the merkle check is supplied by `require Utils.isLeaf(...)` below. It is justified by composition: take's body requires `isRatified(offer, ratifierData) == CALLBACK_SUCCESS`, and both SetterRatifier and EcrecoverRatifier implementations `require(HashLib.isLeaf(root, hashOffer(offer), leafIndex, proof))` for the (root, leafIndex, proof) they decode from ratifierData — regardless of how the maker committed the root (on-chain via `isRootRatified`, or off-chain via EIP-712 signature). -rule takeImpliesLeafInTree( - env e, - uint256 units, address taker, address takerCallback, bytes takerCallbackData, - address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, - bytes32 root, uint256 leafIndex, bytes32[] proof -) { +rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; // Assume that root is the hash of node in the maker's tree. From 07d95e3ed6aea26a67b7436c3c90ea7a9d116901 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 May 2026 18:10:22 +0200 Subject: [PATCH 009/159] fmt --- certora/helpers/OfferTree.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index d7cfd3e1b..221713c90 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -81,8 +81,7 @@ contract OfferTree { if (n.left == 0 || n.right == 0) return false; Node storage L = tree[n.left]; Node storage R = tree[n.right]; - return !_isEmpty(L) && !_isEmpty(R) - && n.hashNode == HashLib.hashNode(L.hashNode, R.hashNode); + return !_isEmpty(L) && !_isEmpty(R) && n.hashNode == HashLib.hashNode(L.hashNode, R.hashNode); } } @@ -97,7 +96,8 @@ contract OfferTree { if (i == 0) break; - // If proof elements remain, the current node must be internal; otherwise the path walks off a leaf's zero children into the unrelated `tree[0]` entry. + // If proof elements remain, the current node must be internal; otherwise the path walks off a leaf's zero + // children into the unrelated `tree[0]` entry. require(!tree[id].isLeaf); bytes32 sibling = proof[--i]; From bcc519888c92e58b144d9877bff4ad920188ec90 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:01:28 +0200 Subject: [PATCH 010/159] renamed spec; minor changes in OfferTree definition --- certora/confs/{TakeCorrectness.conf => OfferTreeMembership.conf} | 0 certora/specs/{TakeCorrectness.spec => OfferTreeMembership.spec} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename certora/confs/{TakeCorrectness.conf => OfferTreeMembership.conf} (100%) rename certora/specs/{TakeCorrectness.spec => OfferTreeMembership.spec} (100%) diff --git a/certora/confs/TakeCorrectness.conf b/certora/confs/OfferTreeMembership.conf similarity index 100% rename from certora/confs/TakeCorrectness.conf rename to certora/confs/OfferTreeMembership.conf diff --git a/certora/specs/TakeCorrectness.spec b/certora/specs/OfferTreeMembership.spec similarity index 100% rename from certora/specs/TakeCorrectness.spec rename to certora/specs/OfferTreeMembership.spec From 38c1875d08f03da3c5e7050d7e6a3492ac1acedd Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:02:19 +0200 Subject: [PATCH 011/159] tuned --- certora/confs/OfferTreeMembership.conf | 4 +-- certora/helpers/OfferTree.sol | 43 +++++++++++++------------- certora/specs/OfferTreeWellFormed.spec | 6 ++-- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index 13e5f2ff9..c00b1f1c8 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -4,7 +4,7 @@ "certora/helpers/OfferTree.sol", "certora/helpers/Utils.sol" ], - "verify": "Midnight:certora/specs/TakeCorrectness.spec", + "verify": "Midnight:certora/specs/OfferTreeMembership.spec", "solc": "solc-0.8.34", "solc_via_ir": true, "solc_evm_version": "osaka", @@ -18,5 +18,5 @@ "-splitParallel true", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" ], - "msg": "TakeCorrectness" + "msg": "Offer Tree Membership" } diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 221713c90..d68b11794 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -12,7 +12,6 @@ contract OfferTree { bytes32 left; bytes32 right; bytes32 hashNode; - bool isLeaf; } /* STORAGE */ @@ -26,26 +25,25 @@ contract OfferTree { Node storage n = tree[leafHash]; require(_isEmpty(n), "leaf already populated"); n.hashNode = leafHash; - n.isLeaf = true; } function newInternalNode(bytes32 id, bytes32 left, bytes32 right) public { require(id != 0, "zero id"); Node storage n = tree[id]; require(_isEmpty(n), "node already populated"); - Node storage L = tree[left]; - Node storage R = tree[right]; - require(!_isEmpty(L), "left empty"); - require(!_isEmpty(R), "right empty"); + bytes32 leftHash = tree[left].hashNode; + bytes32 rightHash = tree[right].hashNode; + require(leftHash != 0, "left empty"); + require(rightHash != 0, "right empty"); n.left = left; n.right = right; - n.hashNode = HashLib.hashNode(L.hashNode, R.hashNode); + n.hashNode = HashLib.hashNode(leftHash, rightHash); } /* PURE AND VIEW FUNCTIONS */ function _isEmpty(Node storage n) internal view returns (bool) { - return n.left == 0 && n.right == 0 && n.hashNode == 0 && !n.isLeaf; + return n.left == 0 && n.right == 0 && n.hashNode == 0; } function isEmpty(bytes32 id) public view returns (bool) { @@ -57,7 +55,7 @@ contract OfferTree { } function isLeafNode(bytes32 id) public view returns (bool) { - return tree[id].isLeaf; + return tree[id].left == 0 && tree[id].right == 0 && tree[id].hashNode != 0; } function getLeft(bytes32 id) public view returns (bytes32) { @@ -69,20 +67,23 @@ contract OfferTree { } // The specification of a well-formed tree is the following: - // - empty nodes are well-formed - // - leaves have id == hashNode and no children - // - internal nodes have non-empty children and hashNode = hashNode(left.hashNode, right.hashNode) + // - empty nodes (all fields zero) are well-formed + // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == id + // - internal nodes (left != 0 && right != 0) require non-empty children and hashNode = hashNode(left.hashNode, right.hashNode) + // - any other field combination is malformed function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; - if (n.isLeaf) { - return n.left == 0 && n.right == 0 && n.hashNode == id && n.hashNode != 0; - } else { - if (n.left == 0 || n.right == 0) return false; - Node storage L = tree[n.left]; - Node storage R = tree[n.right]; - return !_isEmpty(L) && !_isEmpty(R) && n.hashNode == HashLib.hashNode(L.hashNode, R.hashNode); + if (n.left == 0 && n.right == 0) { + return n.hashNode == id; } + if (n.left != 0 && n.right != 0) { + bytes32 leftHash = tree[n.left].hashNode; + bytes32 rightHash = tree[n.right].hashNode; + return leftHash != 0 && rightHash != 0 + && n.hashNode == HashLib.hashNode(leftHash, rightHash); + } + return false; } // Check that the nodes are well-formed starting from `id` and going down the `tree`. @@ -98,7 +99,7 @@ contract OfferTree { // If proof elements remain, the current node must be internal; otherwise the path walks off a leaf's zero // children into the unrelated `tree[0]` entry. - require(!tree[id].isLeaf); + require(!isLeafNode(id)); bytes32 sibling = proof[--i]; @@ -113,7 +114,7 @@ contract OfferTree { id = right; } } - require(tree[id].isLeaf); + require(isLeafNode(id)); return id; } } diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index f9b941425..3fa87d390 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,10 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2025 Morpho Association -// Rule A — Well-formed offer-tree invariant. -// -// Verifies that the helper's only mutators (`newLeaf`, `newInternalNode`) -// preserve `isWellFormed` for every node id. This justifies using the helper +// Verifies that the tree construction via `newLeaf` and `newInternalNode` +// preserves `isWellFormed` for every node id. This justifies using the helper // as a ghost tree to reason about Midnight's runtime merkle verification. methods { From 8208a49ca589f5cf1ea4ee49aaa25c917c15654a Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:07:31 +0200 Subject: [PATCH 012/159] fmt --- certora/specs/OfferTreeMembership.spec | 57 +++++++++++--------------- certora/specs/OfferTreeWellFormed.spec | 5 --- 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index f381cd7c8..6095dbbf7 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// Copyright (c) 2025 Morpho Association using OfferTree as OfferTree; using Utils as Utils; methods { - function isAuthorized(address authorizer, address authorized) external returns (bool) envfree; + function isAuthorized(address, address) external returns (bool) envfree; function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; @@ -15,15 +14,12 @@ methods { function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. + // Align the merkle verification and the helper's well-formedness on the same injective hash functions. function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - - // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); - // Take-side externals summarized as NONDET / havoc — irrelevant to the merkle-membership property. - // `isRatified` is NONDET'd so the rule abstracts over the ratifier choice: the bridge from - // `take ⇒ Utils.isLeaf success` is supplied explicitly in `takeImpliesLeafInTree` below. + // Take-side externals are irrelevant to merkle membership. `isRatified` is NONDET'd so the rule + // abstracts over the ratifier choice; the bridge to `Utils.isLeaf` is supplied in the rule body. function _.isRatified(Midnight.Offer, bytes) external => NONDET; function _.onBuy(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; function _.onSell(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; @@ -53,55 +49,48 @@ function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { return ghostHashNode(a, b); } -// The main correctness result of the verification. -// If a maker-ratified root corresponds to a node of a well-formed offer-tree, then a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. +/// SOUNDNESS /// + +/// If a root corresponds to a node of a well-formed offer-tree, a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; + require OfferTree.getHash(node) == root, "root is the hash of node"; + require root != to_bytes32(0), "root is non-zero"; - // Assume that root is the hash of node in the tree. - require OfferTree.getHash(node) == root; - require root != to_bytes32(0); - - // Assume that the tree is well-formed along the proof path from node down to a leaf. OfferTree.wellFormedPath(node, leafIndex, proof); - // Compute the leaf hash once so both uses below bind to the same symbolic value. + // Compute leafId once so both uses below bind to the same symbolic hash. bytes32 leafId = Utils.hashOffer(offer); - - require Utils.isLeaf(root, leafId, leafIndex, proof); + require Utils.isLeaf(root, leafId, leafIndex, proof), "merkle proof verifies"; assert OfferTree.isLeafNode(leafId); } -// The completeness dual of takeCorrectness. -// Every leaf in a well-formed offer-tree has a verifying merkle proof: folding the path's sibling hashes back up against the leaf reproduces the root. +/// COMPLETENESS /// + +/// Every leaf in a well-formed offer-tree has a verifying merkle proof: folding the path's sibling hashes back up against the leaf reproduces the root. rule takeCompleteness(bytes32 node, bytes32 root, uint256 leafIndex, bytes32[] proof) { - // Assume that root is the hash of node in the tree. - require OfferTree.getHash(node) == root; - require root != to_bytes32(0); + require OfferTree.getHash(node) == root, "root is the hash of node"; + require root != to_bytes32(0), "root is non-zero"; - // Walk the well-formed path; the call returns the leaf at the bottom. bytes32 endLeaf = OfferTree.wellFormedPath(node, leafIndex, proof); assert Utils.isLeaf(root, endLeaf, leafIndex, proof); } -// The take-level guarantee: every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. -// The bridge from take's success to the merkle check is supplied by `require Utils.isLeaf(...)` below. It is justified by composition: take's body requires `isRatified(offer, ratifierData) == CALLBACK_SUCCESS`, and both SetterRatifier and EcrecoverRatifier implementations `require(HashLib.isLeaf(root, hashOffer(offer), leafIndex, proof))` for the (root, leafIndex, proof) they decode from ratifierData — regardless of how the maker committed the root (on-chain via `isRootRatified`, or off-chain via EIP-712 signature). +/// TAKE-LEVEL LIFT /// + +/// Every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. +/// The `require Utils.isLeaf(...)` below is the bridge from take to the merkle check, justified by composition: take requires `isRatified(...) == CALLBACK_SUCCESS`, and both SetterRatifier and EcrecoverRatifier require HashLib.isLeaf to pass. rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; + require OfferTree.getHash(node) == root, "root is the hash of node"; + require root != to_bytes32(0), "root is non-zero"; - // Assume that root is the hash of node in the maker's tree. - require OfferTree.getHash(node) == root; - require root != to_bytes32(0); - - // Assume that the tree is well-formed along the proof path from node down to a leaf. OfferTree.wellFormedPath(node, leafIndex, proof); bytes32 leafId = Utils.hashOffer(offer); - - // Bridge: a successful take implies the chosen ratifier's `isRatified` returned CALLBACK_SUCCESS, which implies `HashLib.isLeaf(...)` passed for the (root, leafIndex, proof) it decoded from ratifierData. We model that decoded triple as the rule's (root, leafIndex, proof). - require Utils.isLeaf(root, leafId, leafIndex, proof); + require Utils.isLeaf(root, leafId, leafIndex, proof), "ratifier bridge: matches the merkle check inside isRatified"; take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData); diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 3fa87d390..c584c5cd6 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,9 +1,4 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// Copyright (c) 2025 Morpho Association - -// Verifies that the tree construction via `newLeaf` and `newInternalNode` -// preserves `isWellFormed` for every node id. This justifies using the helper -// as a ghost tree to reason about Midnight's runtime merkle verification. methods { function isEmpty(bytes32) external returns (bool) envfree; From 80d2ad2697f303234b8463c8a8fe04d7ad96dca8 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:10:46 +0200 Subject: [PATCH 013/159] forge fmt --- certora/helpers/OfferTree.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index d68b11794..d371eeaff 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -69,8 +69,8 @@ contract OfferTree { // The specification of a well-formed tree is the following: // - empty nodes (all fields zero) are well-formed // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == id - // - internal nodes (left != 0 && right != 0) require non-empty children and hashNode = hashNode(left.hashNode, right.hashNode) - // - any other field combination is malformed + // - internal nodes (left != 0 && right != 0) require non-empty children and hashNode = hashNode(left.hashNode, + // right.hashNode) - any other field combination is malformed function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; @@ -80,8 +80,7 @@ contract OfferTree { if (n.left != 0 && n.right != 0) { bytes32 leftHash = tree[n.left].hashNode; bytes32 rightHash = tree[n.right].hashNode; - return leftHash != 0 && rightHash != 0 - && n.hashNode == HashLib.hashNode(leftHash, rightHash); + return leftHash != 0 && rightHash != 0 && n.hashNode == HashLib.hashNode(leftHash, rightHash); } return false; } From 03ba8cdd4201e054622c7fac95079c56f7d503e6 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:36:02 +0200 Subject: [PATCH 014/159] resolved errors from merge --- certora/specs/OfferTreeMembership.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 6095dbbf7..e8d2764a3 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -92,7 +92,7 @@ rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCal bytes32 leafId = Utils.hashOffer(offer); require Utils.isLeaf(root, leafId, leafIndex, proof), "ratifier bridge: matches the merkle check inside isRatified"; - take(e, units, taker, takerCallback, takerCallbackData, receiverIfTakerIsSeller, offer, ratifierData); + take(e, offer, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData, ratifierData); assert OfferTree.isLeafNode(leafId); } From dd415d017dc728a9ab8a49dcd456869f2ab9910c Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 10:42:07 +0200 Subject: [PATCH 015/159] updated callback summary signatures --- certora/specs/OfferTreeMembership.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index e8d2764a3..f408be60e 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -21,8 +21,8 @@ methods { // Take-side externals are irrelevant to merkle membership. `isRatified` is NONDET'd so the rule // abstracts over the ratifier choice; the bridge to `Utils.isLeaf` is supplied in the rule body. function _.isRatified(Midnight.Offer, bytes) external => NONDET; - function _.onBuy(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; - function _.onSell(bytes32, Midnight.Market, address, uint256, uint256, bytes) external => NONDET; + function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; + function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; function _.transferFrom(address, address, uint256) external => NONDET; function _.transfer(address, uint256) external => NONDET; function multicall(bytes[]) external => HAVOC_ALL DELETE; From 24140f4b77a2c77d4dae34dd2fc3d7a7bfb31ab6 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 11:23:04 +0200 Subject: [PATCH 016/159] new rule in Ratification.spec: isRatified always calls isLeaf --- certora/confs/Ratification.conf | 7 ++++-- certora/helpers/Utils.sol | 4 ++++ certora/specs/Ratification.spec | 40 +++++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/certora/confs/Ratification.conf b/certora/confs/Ratification.conf index ee35ddd4c..1a2010582 100644 --- a/certora/confs/Ratification.conf +++ b/certora/confs/Ratification.conf @@ -1,10 +1,13 @@ { "files": [ "src/Midnight.sol", - "src/ratifiers/EcrecoverRatifier.sol" + "src/ratifiers/EcrecoverRatifier.sol", + "src/ratifiers/SetterRatifier.sol", + "certora/helpers/Utils.sol" ], "link": [ - "EcrecoverRatifier:MIDNIGHT=Midnight" + "EcrecoverRatifier:MIDNIGHT=Midnight", + "SetterRatifier:MIDNIGHT=Midnight" ], "verify": "Midnight:certora/specs/Ratification.spec", "solc": "solc-0.8.34", diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index c8dabebcf..1f8aa03d0 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -22,6 +22,10 @@ contract Utils { return keccak256(abi.encode(offer)); } + function hashNode(bytes32 a, bytes32 b) external pure returns (bytes32) { + return keccak256(abi.encode(a, b)); + } + function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) external pure diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index c99cd04b6..8a02fc2b7 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -1,18 +1,28 @@ // SPDX-License-Identifier: GPL-2.0-or-later +using Utils as Utils; + methods { function multicall(bytes[]) external => HAVOC_ALL DELETE; function isAuthorized(address authorizer, address authorized) external returns (bool) envfree; + function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + function Utils.callbackSuccess() external returns (bytes32) envfree; + function _.isRatified(Midnight.Offer, bytes) external => DISPATCHER(true); function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; function _.transferFrom(address, address, uint256) external => NONDET; function _.transfer(address, uint256) external => NONDET; - function HashLib.isLeaf(bytes32, bytes32, uint256, bytes32[] memory) internal returns (bool) => NONDET; + + // Capture HashLib.isLeaf's args + return; needed by `isRatifiedRequiresIsLeaf`. + function HashLib.isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) internal returns (bool) => isLeafCapture(root, leafHash, leafIndex, proof); + + // Route hashOffer through Utils so the rule can equate the captured leafHash to hashOffer(offer). + function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); + function HashLib.offerTreeTypeHash(uint256) internal returns (bytes32) => NONDET; - function HashLib.hashOffer(Midnight.Offer memory) internal returns (bytes32) => NONDET; // Summaries for internals irrelevant to ratification properties. function IdLib.toId(Midnight.Market memory, uint256, address) internal returns (bytes32) => NONDET; @@ -25,6 +35,22 @@ methods { function tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; } +function summaryHashOffer(Midnight.Offer offer) returns bytes32 { + return Utils.hashOffer(offer); +} + +// Captures whether HashLib.isLeaf was called and returned true during the current rule. +// Used by `isRatifiedRequiresIsLeaf` to assert that every successful isRatified gates on a merkle check. +persistent ghost bool isLeafReturnedTrue; + +function isLeafCapture(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] proof) returns bool { + bool ret; + if (ret) { + isLeafReturnedTrue = true; + } + return ret; +} + /// Every successful take requires the maker to have authorized the ratifier. rule takeRequiresMakerConsent(env e, Midnight.Offer offer, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData, bytes ratifierData) { bool makerAuthorizedRatifier = isAuthorized(offer.maker, offer.ratifier); @@ -52,3 +78,13 @@ rule takeRequiresNonZeroMaker(env e, Midnight.Offer offer, uint256 units, addres take(e, offer, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData, ratifierData); assert offer.maker != 0; } + +/// Every successful isRatified call implies HashLib.isLeaf was invoked and returned true. Verified by dispatch across all linked ratifier implementations. +rule isRatifiedRequiresIsLeaf(env e, address ratifierAddr, Midnight.Offer offer, bytes ratifierData) { + require !isLeafReturnedTrue, "fresh capture state"; + + bytes32 result = ratifierAddr.isRatified(e, offer, ratifierData); + require result == Utils.callbackSuccess(), "isRatified succeeded"; + + assert isLeafReturnedTrue, "ratifier must have called HashLib.isLeaf that returned true"; +} From cfb723f7d15d4af477a0496aab0cc3b7c781f34c Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 20 May 2026 11:23:46 +0200 Subject: [PATCH 017/159] rhashNode summarised similar to hashOffer --- certora/specs/OfferTreeMembership.spec | 10 +++------- certora/specs/SetterRatification.spec | 14 +++++--------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index f408be60e..bd614c40c 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -12,9 +12,10 @@ methods { function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - // Align the merkle verification and the helper's well-formedness on the same injective hash functions. + // Align the merkle verification and the helper's well-formedness on the same hash functions. function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); @@ -40,13 +41,8 @@ function summaryHashOffer(Midnight.Offer offer) returns bytes32 { return Utils.hashOffer(offer); } -// Injective on ordered pairs. -persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { - axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); -} - function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { - return ghostHashNode(a, b); + return Utils.hashNode(a, b); } /// SOUNDNESS /// diff --git a/certora/specs/SetterRatification.spec b/certora/specs/SetterRatification.spec index 673ed887e..06c4b7c72 100644 --- a/certora/specs/SetterRatification.spec +++ b/certora/specs/SetterRatification.spec @@ -12,14 +12,15 @@ methods { function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; + function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; function SetterRatifier.isRootRatified(address, bytes32) external returns (bool) envfree; - // Summarized so the merkle verification and the helper-side leaf hash agree on the leaf-hash function. + // Align the merkle verification and the helper's well-formedness on the same hash functions. + // Routing through Utils (`keccak256(abi.encode(...))`) lets Certora's bounded-hash recognition + // supply injectivity automatically, instead of needing a ghost + axiom. function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - - // Summarized to a ghost so the upward fold and the downward walk see the same injective hash function. function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); } @@ -27,13 +28,8 @@ function summaryHashOffer(Midnight.Offer offer) returns bytes32 { return Utils.hashOffer(offer); } -// Injective on ordered pairs. -persistent ghost ghostHashNode(bytes32, bytes32) returns bytes32 { - axiom forall bytes32 a1. forall bytes32 b1. forall bytes32 a2. forall bytes32 b2. ghostHashNode(a1, b1) == ghostHashNode(a2, b2) => (a1 == a2 && b1 == b2); -} - function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { - return ghostHashNode(a, b); + return Utils.hashNode(a, b); } // SetterRatifier-specific framing of takeCorrectness. From 8187c247889fab11f4168312662d715c99b90aec Mon Sep 17 00:00:00 2001 From: Bhargav Date: Thu, 21 May 2026 14:18:49 +0200 Subject: [PATCH 018/159] revamped soundness: Offer included in the node --- certora/helpers/OfferTree.sol | 52 ++++++++++---------------- certora/specs/OfferTreeMembership.spec | 17 ++------- certora/specs/Ratification.spec | 6 +-- 3 files changed, 25 insertions(+), 50 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index d371eeaff..8c8e45ede 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -2,15 +2,18 @@ // Copyright (c) 2025 Morpho Association pragma solidity ^0.8.0; +import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; -// Ghost offer-tree helper used by Certora specs. // Trees are built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by construction. -// Specs supply leaf hashes externally; the helper does not encode the Offer struct itself. +// Leaves carry the offer payload so `isWellFormed` can pin a leaf's `hashNode` into the image of +// `hashOffer` (distinct keccak input shape from `hashNode`), giving domain separation against internal-node +// hashes for free under Certora's keccak model. contract OfferTree { struct Node { bytes32 left; bytes32 right; + Offer offer; bytes32 hashNode; } @@ -20,11 +23,13 @@ contract OfferTree { /* MAIN FUNCTIONS */ - function newLeaf(bytes32 leafHash) public { - require(leafHash != 0, "zero leaf hash"); - Node storage n = tree[leafHash]; + function newLeaf(Offer memory offer) public { + bytes32 id = HashLib.hashOffer(offer); + require(id != 0, "zero offer hash"); + Node storage n = tree[id]; require(_isEmpty(n), "leaf already populated"); - n.hashNode = leafHash; + n.offer = offer; + n.hashNode = id; } function newInternalNode(bytes32 id, bytes32 left, bytes32 right) public { @@ -67,15 +72,16 @@ contract OfferTree { } // The specification of a well-formed tree is the following: - // - empty nodes (all fields zero) are well-formed - // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == id + // - empty nodes (left == 0 && right == 0 && hashNode == 0) are well-formed + // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == hashOffer(offer) and id == hashNode // - internal nodes (left != 0 && right != 0) require non-empty children and hashNode = hashNode(left.hashNode, // right.hashNode) - any other field combination is malformed function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; if (n.left == 0 && n.right == 0) { - return n.hashNode == id; + bytes32 expected = HashLib.hashOffer(n.offer); + return n.hashNode == expected && id == expected; } if (n.left != 0 && n.right != 0) { bytes32 leftHash = tree[n.left].hashNode; @@ -86,34 +92,16 @@ contract OfferTree { } // Check that the nodes are well-formed starting from `id` and going down the `tree`. - // The bits of `leafIndex` choose the path downward; `proof` supplies the sibling hashes consumed from end to start. - // The path must terminate at a leaf, matching the depth implied by `proof.length`. - // Returns the id of the leaf at the bottom of the path. - function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bytes32) { - require(leafIndex >> proof.length == 0, "leaf index out of range"); + // The bits of `leafIndex` choose the path downward; the depth is `proof.length`. + function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bool) { for (uint256 i = proof.length;;) { require(isWellFormed(id)); if (i == 0) break; - // If proof elements remain, the current node must be internal; otherwise the path walks off a leaf's zero - // children into the unrelated `tree[0]` entry. - require(!isLeafNode(id)); - - bytes32 sibling = proof[--i]; - - bytes32 left = tree[id].left; - bytes32 right = tree[id].right; - - if ((leafIndex >> i) & 1 == 0) { - require(getHash(right) == sibling); - id = left; - } else { - require(getHash(left) == sibling); - id = right; - } + --i; + id = ((leafIndex >> i) & 1 == 0) ? tree[id].left : tree[id].right; } - require(isLeafNode(id)); - return id; + return true; } } diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index bd614c40c..dd1e00c45 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -9,7 +9,7 @@ methods { function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; - function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; + function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; @@ -57,23 +57,12 @@ rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, byte // Compute leafId once so both uses below bind to the same symbolic hash. bytes32 leafId = Utils.hashOffer(offer); + require leafId != to_bytes32(0), "leafId is non-zero"; require Utils.isLeaf(root, leafId, leafIndex, proof), "merkle proof verifies"; assert OfferTree.isLeafNode(leafId); } -/// COMPLETENESS /// - -/// Every leaf in a well-formed offer-tree has a verifying merkle proof: folding the path's sibling hashes back up against the leaf reproduces the root. -rule takeCompleteness(bytes32 node, bytes32 root, uint256 leafIndex, bytes32[] proof) { - require OfferTree.getHash(node) == root, "root is the hash of node"; - require root != to_bytes32(0), "root is non-zero"; - - bytes32 endLeaf = OfferTree.wellFormedPath(node, leafIndex, proof); - - assert Utils.isLeaf(root, endLeaf, leafIndex, proof); -} - /// TAKE-LEVEL LIFT /// /// Every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. @@ -86,7 +75,7 @@ rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCal OfferTree.wellFormedPath(node, leafIndex, proof); bytes32 leafId = Utils.hashOffer(offer); - require Utils.isLeaf(root, leafId, leafIndex, proof), "ratifier bridge: matches the merkle check inside isRatified"; + require Utils.isLeaf(root, leafId, leafIndex, proof); take(e, offer, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData, ratifierData); diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index 8a02fc2b7..9430ad465 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -16,12 +16,10 @@ methods { function _.transferFrom(address, address, uint256) external => NONDET; function _.transfer(address, uint256) external => NONDET; - // Capture HashLib.isLeaf's args + return; needed by `isRatifiedRequiresIsLeaf`. + // Capture HashLib.isLeaf's return; needed by `isRatifiedRequiresIsLeaf` to assert isRatified gates on a merkle check. function HashLib.isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) internal returns (bool) => isLeafCapture(root, leafHash, leafIndex, proof); - // Route hashOffer through Utils so the rule can equate the captured leafHash to hashOffer(offer). - function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - + function HashLib.hashOffer(Midnight.Offer memory) internal returns (bytes32) => NONDET; function HashLib.offerTreeTypeHash(uint256) internal returns (bytes32) => NONDET; // Summaries for internals irrelevant to ratification properties. From 2d1eb8747367acf9d6004d1c3d2daf18493ace97 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Thu, 21 May 2026 16:17:57 +0200 Subject: [PATCH 019/159] tuned comment --- certora/helpers/OfferTree.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 8c8e45ede..4024829d4 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -25,9 +25,9 @@ contract OfferTree { function newLeaf(Offer memory offer) public { bytes32 id = HashLib.hashOffer(offer); - require(id != 0, "zero offer hash"); + require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; - require(_isEmpty(n), "leaf already populated"); + require(_isEmpty(n), "leaf is not empty"); n.offer = offer; n.hashNode = id; } From d77d0b3994c91d764acfdc3038135dd29cae1220 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 26 May 2026 00:37:47 +0200 Subject: [PATCH 020/159] add checker --- certora/checker/Checker.sol | 371 ++++++++++++++++++++++++++ certora/checker/create_certificate.py | 275 +++++++++++++++++++ 2 files changed, 646 insertions(+) create mode 100644 certora/checker/Checker.sol create mode 100644 certora/checker/create_certificate.py diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol new file mode 100644 index 000000000..fe41dff06 --- /dev/null +++ b/certora/checker/Checker.sol @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association +pragma solidity ^0.8.0; + +import {Test} from "../../lib/forge-std/src/Test.sol"; +import {stdJson} from "../../lib/forge-std/src/StdJson.sol"; + +import {OfferTree} from "../helpers/OfferTree.sol"; +import {Offer, Market, CollateralParams} from "../../src/interfaces/IMidnight.sol"; +import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; +import {EIP712_DOMAIN_TYPEHASH} from "../../src/ratifiers/interfaces/IEcrecoverRatifier.sol"; + +contract Checker is Test { + using stdJson for string; + + struct Eip712Envelope { + address ratifier; + uint256 chainId; + uint256 height; + address signer; + uint8 v; + bytes32 r; + bytes32 s; + } + + // Rebuild a dense tree level-by-level via the verified `newLeaf` and + // `newInternalNode` primitives and assert the top hash matches `root`. + // Inserts are skipped when the target slot is already populated, so duplicate + // leaves (e.g. an `emptyOffer` repeated across padding slots) collapse into a + // single helper slot. + function _verifyDense(Offer[] memory leaves, bytes32 root) internal { + require(leaves.length > 0, "no leaves"); + require((leaves.length & (leaves.length - 1)) == 0, "leaves length not power of two"); + + OfferTree tree = new OfferTree(); + + bytes32[] memory level = new bytes32[](leaves.length); + for (uint256 i = 0; i < leaves.length; i++) { + bytes32 leafHash = HashLib.hashOffer(leaves[i]); + if (tree.isEmpty(leafHash)) tree.newLeaf(leaves[i]); + level[i] = leafHash; + } + + while (level.length > 1) { + uint256 half = level.length / 2; + bytes32[] memory next = new bytes32[](half); + for (uint256 i = 0; i < half; i++) { + bytes32 leftHash = level[2 * i]; + bytes32 rightHash = level[2 * i + 1]; + bytes32 nodeHash = HashLib.hashNode(leftHash, rightHash); + if (tree.isEmpty(nodeHash)) tree.newInternalNode(nodeHash, leftHash, rightHash); + next[i] = nodeHash; + } + level = next; + } + + assertEq(level[0], root, "dense: root mismatch"); + } + + // Internal nodes must be supplied in topological order (children before parents). + // The last id is taken as the root. + function _verifySparse( + Offer[] memory leaves, + bytes32[] memory nodeIds, + bytes32[] memory nodeLefts, + bytes32[] memory nodeRights, + bytes32 root + ) internal { + require(nodeIds.length == nodeLefts.length, "node arrays length mismatch"); + require(nodeIds.length == nodeRights.length, "node arrays length mismatch"); + require(nodeIds.length > 0, "no internal nodes"); + + OfferTree tree = new OfferTree(); + + for (uint256 i = 0; i < leaves.length; i++) { + bytes32 leafHash = HashLib.hashOffer(leaves[i]); + if (tree.isEmpty(leafHash)) tree.newLeaf(leaves[i]); + } + for (uint256 i = 0; i < nodeIds.length; i++) { + if (tree.isEmpty(nodeIds[i])) { + tree.newInternalNode(nodeIds[i], nodeLefts[i], nodeRights[i]); + } + } + + bytes32 rootId = nodeIds[nodeIds.length - 1]; + assertEq(tree.getHash(rootId), root, "sparse: root mismatch"); + } + + // Mirrors EcrecoverRatifier.isRatified: structHash wraps the offer-tree typehash + // and root, the domain separator binds (chainId, ratifier), and the digest is the + // standard EIP-712 form. + function _verifyEip712(bytes32 root, Eip712Envelope memory env) internal { + bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(env.height), root)); + bytes32 domainSeparator = + keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, env.chainId, env.ratifier)); + bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); + address recovered = ecrecover(digest, env.v, env.r, env.s); + require(recovered != address(0), "eip712: invalid signature"); + assertEq(recovered, env.signer, "eip712: signer mismatch"); + } + + function _maybeVerifyEip712(string memory json, bytes32 root, uint256 leafLength) internal { + if (!json.keyExists(".eip712")) return; + + Eip712Envelope memory env; + env.ratifier = json.readAddress(".eip712.ratifier"); + env.chainId = json.readUint(".eip712.chainId"); + env.height = json.readUint(".eip712.height"); + env.signer = json.readAddress(".eip712.signer"); + env.v = uint8(json.readUint(".eip712.v")); + env.r = json.readBytes32(".eip712.r"); + env.s = json.readBytes32(".eip712.s"); + + require(1 << env.height == leafLength, "eip712: height does not match leaf count"); + _verifyEip712(root, env); + } + + function testVerifyCertificate() public { + string memory path = string.concat(vm.projectRoot(), "/certificate.json"); + if (!vm.exists(path)) vm.skip(true, "no certificate.json at project root"); + + string memory json = vm.readFile(path); + string memory mode = json.readString(".mode"); + bytes32 root = json.readBytes32(".root"); + + uint256 leafLength = json.readUint(".leafLength"); + Offer[] memory leaves = new Offer[](leafLength); + for (uint256 i = 0; i < leafLength; i++) { + bytes memory enc = json.readBytes(string.concat(".leaf[", vm.toString(i), "]")); + leaves[i] = abi.decode(enc, (Offer)); + } + + bytes32 modeHash = keccak256(bytes(mode)); + if (modeHash == keccak256("dense")) { + _verifyDense(leaves, root); + _maybeVerifyEip712(json, root, leafLength); + } else if (modeHash == keccak256("sparse")) { + uint256 nodeLength = json.readUint(".nodeLength"); + bytes32[] memory ids = new bytes32[](nodeLength); + bytes32[] memory lefts = new bytes32[](nodeLength); + bytes32[] memory rights = new bytes32[](nodeLength); + for (uint256 i = 0; i < nodeLength; i++) { + string memory base = string.concat(".node[", vm.toString(i), "]"); + ids[i] = json.readBytes32(string.concat(base, ".id")); + lefts[i] = json.readBytes32(string.concat(base, ".left")); + rights[i] = json.readBytes32(string.concat(base, ".right")); + } + _verifySparse(leaves, ids, lefts, rights, root); + } else { + revert("unknown certificate mode"); + } + } + + function testSyntheticDenseHeight2() public { + Offer[] memory leaves = new Offer[](4); + for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); + + bytes32 h0 = HashLib.hashOffer(leaves[0]); + bytes32 h1 = HashLib.hashOffer(leaves[1]); + bytes32 h2 = HashLib.hashOffer(leaves[2]); + bytes32 h3 = HashLib.hashOffer(leaves[3]); + bytes32 leftBranch = HashLib.hashNode(h0, h1); + bytes32 rightBranch = HashLib.hashNode(h2, h3); + bytes32 root = HashLib.hashNode(leftBranch, rightBranch); + + _verifyDense(leaves, root); + } + + function testSyntheticDenseHeight2DetectsRootMismatch() public { + Offer[] memory leaves = new Offer[](4); + for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); + + vm.expectRevert(); + this.externalVerifyDense(leaves, bytes32(uint256(0xdeadbeef))); + } + + function testSyntheticDenseHeight2WithEmptyPadding() public { + Offer memory emptyOffer; + Offer memory real = _dummyOffer(42); + + Offer[] memory leaves = new Offer[](4); + leaves[0] = real; + leaves[1] = emptyOffer; + leaves[2] = emptyOffer; + leaves[3] = emptyOffer; + + bytes32 hReal = HashLib.hashOffer(real); + bytes32 hEmpty = HashLib.hashOffer(emptyOffer); + bytes32 leftBranch = HashLib.hashNode(hReal, hEmpty); + bytes32 rightBranch = HashLib.hashNode(hEmpty, hEmpty); + bytes32 root = HashLib.hashNode(leftBranch, rightBranch); + + _verifyDense(leaves, root); + } + + function testSyntheticDenseHeight2AllEmpty() public { + Offer memory emptyOffer; + + Offer[] memory leaves = new Offer[](4); + leaves[0] = emptyOffer; + leaves[1] = emptyOffer; + leaves[2] = emptyOffer; + leaves[3] = emptyOffer; + + bytes32 hEmpty = HashLib.hashOffer(emptyOffer); + bytes32 inner = HashLib.hashNode(hEmpty, hEmpty); + bytes32 root = HashLib.hashNode(inner, inner); + + _verifyDense(leaves, root); + } + + function testSyntheticEip712Height2() public { + Offer[] memory leaves = new Offer[](4); + for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); + + bytes32 h0 = HashLib.hashOffer(leaves[0]); + bytes32 h1 = HashLib.hashOffer(leaves[1]); + bytes32 h2 = HashLib.hashOffer(leaves[2]); + bytes32 h3 = HashLib.hashOffer(leaves[3]); + bytes32 root = HashLib.hashNode(HashLib.hashNode(h0, h1), HashLib.hashNode(h2, h3)); + + address ratifier = address(uint160(0xA17F1E7)); + uint256 chainId = 1; + uint256 height = 2; + uint256 privateKey = 0xA11CE; + + bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); + bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); + bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); + + _verifyDense(leaves, root); + _verifyEip712( + root, + Eip712Envelope({ + ratifier: ratifier, + chainId: chainId, + height: height, + signer: vm.addr(privateKey), + v: v, + r: r, + s: s + }) + ); + } + + function testSyntheticEip712DetectsSignerMismatch() public { + Offer[] memory leaves = new Offer[](2); + leaves[0] = _dummyOffer(300); + leaves[1] = _dummyOffer(301); + + bytes32 root = HashLib.hashNode(HashLib.hashOffer(leaves[0]), HashLib.hashOffer(leaves[1])); + + address ratifier = address(uint160(0xA17F1E7)); + uint256 chainId = 1; + uint256 height = 1; + + bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); + bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); + bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(uint256(0xB0B), digest); + + Eip712Envelope memory env = Eip712Envelope({ + ratifier: ratifier, + chainId: chainId, + height: height, + signer: vm.addr(uint256(0xDEADBEEF)), + v: v, + r: r, + s: s + }); + + vm.expectRevert(); + this.externalVerifyEip712(root, env); + } + + function testSyntheticEip712DetectsWrongRoot() public { + Offer[] memory leaves = new Offer[](2); + leaves[0] = _dummyOffer(400); + leaves[1] = _dummyOffer(401); + + bytes32 root = HashLib.hashNode(HashLib.hashOffer(leaves[0]), HashLib.hashOffer(leaves[1])); + + address ratifier = address(uint160(0xA17F1E7)); + uint256 chainId = 1; + uint256 height = 1; + uint256 privateKey = 0xC0FFEE; + + bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); + bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); + bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); + + Eip712Envelope memory env = Eip712Envelope({ + ratifier: ratifier, + chainId: chainId, + height: height, + signer: vm.addr(privateKey), + v: v, + r: r, + s: s + }); + + vm.expectRevert(); + this.externalVerifyEip712(keccak256(abi.encode(root, "tamper")), env); + } + + function testSyntheticSparseTwoLeaves() public { + Offer[] memory leaves = new Offer[](2); + leaves[0] = _dummyOffer(100); + leaves[1] = _dummyOffer(101); + + bytes32 leftHash = HashLib.hashOffer(leaves[0]); + bytes32 rightHash = HashLib.hashOffer(leaves[1]); + bytes32 root = HashLib.hashNode(leftHash, rightHash); + + bytes32[] memory ids = new bytes32[](1); + bytes32[] memory lefts = new bytes32[](1); + bytes32[] memory rights = new bytes32[](1); + ids[0] = root; + lefts[0] = leftHash; + rights[0] = rightHash; + + _verifySparse(leaves, ids, lefts, rights, root); + } + + function testSyntheticSparseDepth2OneActivePath() public { + Offer[] memory leaves = new Offer[](3); + leaves[0] = _dummyOffer(200); + leaves[1] = _dummyOffer(201); + leaves[2] = _dummyOffer(202); + + bytes32 h0 = HashLib.hashOffer(leaves[0]); + bytes32 h1 = HashLib.hashOffer(leaves[1]); + bytes32 hUncle = HashLib.hashOffer(leaves[2]); + bytes32 leftBranch = HashLib.hashNode(h0, h1); + bytes32 root = HashLib.hashNode(leftBranch, hUncle); + + bytes32[] memory ids = new bytes32[](2); + bytes32[] memory lefts = new bytes32[](2); + bytes32[] memory rights = new bytes32[](2); + + ids[0] = leftBranch; + lefts[0] = h0; + rights[0] = h1; + ids[1] = root; + lefts[1] = leftBranch; + rights[1] = hUncle; + + _verifySparse(leaves, ids, lefts, rights, root); + } + + // External wrappers so `vm.expectRevert` can catch internal-call reverts. + function externalVerifyDense(Offer[] memory leaves, bytes32 root) external { + _verifyDense(leaves, root); + } + + function externalVerifyEip712(bytes32 root, Eip712Envelope memory env) external { + _verifyEip712(root, env); + } + + // Distinct dummy offers, distinguished by `tick`. + function _dummyOffer(uint256 nonce) internal pure returns (Offer memory o) { + o.market.loanToken = address(uint160(0x1000 + nonce)); + o.market.collateralParams = new CollateralParams[](0); + o.maker = address(uint160(0x2000 + nonce)); + o.tick = nonce; + o.maxUnits = 1; + o.maxAssets = 1; + } +} diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py new file mode 100644 index 000000000..5982af4d7 --- /dev/null +++ b/certora/checker/create_certificate.py @@ -0,0 +1,275 @@ +import json +import sys + +from eth_abi import encode +from eth_account import Account +from web3 import EthereumTesterProvider, Web3 + +w3 = Web3(EthereumTesterProvider()) + +# keccak256("EIP712Domain(uint256 chainId,address verifyingContract)"). +EIP712_DOMAIN_TYPEHASH = bytes.fromhex( + "47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218" +) + +# Precomputed offerTreeTypeHash(h) for h in 0..20; mirrors HashLib.offerTreeTypeHash. +OFFER_TREE_TYPE_HASHES = [ + "2b9ee710e1977dfc5778fe18c905ccc1d9e144baf3ba83be732d4da65ecb73e3", + "3cc16189b92a85898f1d5c6e87282c8ded7c1c93b2323d5e85ae10c5f4b2b220", + "6de37d3e570afa293a8107d4b6b1d9547616c04f42164d009c89194787b2ffa6", + "ba3ea2ddfbf40a906fcd1b9506dbd344c062e8dcba8b5c902ceb13339f45a358", + "e5faa865e93bc1b7b8fdf91980f54682d649683b014edd6c54b642f5a0c96977", + "eda50f61dd2a827c6ff9fbfcd54335628dcaa78aaa4f2d118c60886219cdce2b", + "54e2c9cc40cdc0e9ad530cf2be298f952f57af2b18b02f88274a9bbab359d23a", + "c9d81859d60d6b21c688f4be93ca83e3be222728bb156ef5f4cf497f879f1e29", + "d59b0c4544e0c60c8611eab0aaa402575f14ee784d22289c5d57f48c422a62d6", + "ccad21701f34f08bb8398a3dbc77e20e4c9c424930f3a8b31485bf059e2bdb20", + "8a42dfb49807647bfc49c906aef322aa0239d40e4cb675761e141bc7bfa530da", + "2adc0d948b2e3ecb642661590d2eec36d4e71e9acf382deb6574371800caf198", + "f5845dfaed016de272342f346346a49d4b1694f622144d420558a38e46ac9dad", + "3d7df854e6294bf433b64bbb8d0a82fa875a87b45b0016db27fc5752e54126ad", + "72a991a101708716ff427c524404ab44f4d4d1f4e7e76c0ae8b967222164b348", + "762c88fc52cf78a54401d247790f1bdb619d51d3458d1415c20d1422197cecc4", + "8ede2209e94c8d5f8379d733dc8712b71a3888c1c4b70f3d6b22285f70bf4286", + "425b18f07b3ac2f641977d2c294590565dd40b5d8414610568dca64628399975", + "7e7d98718c0180e882e5963b9bd49810096912c273dfa38d8afdd6d39fde86ec", + "8d35d491a29d846489e19688efff3c4cc7dbd54458058d49b30294074539f0b9", + "824e385eea1953bcbc783bf900b18aa6fba129b6908765e986cf0968b491ec4f", +] + +# ABI signature for `Offer` matching src/interfaces/IMidnight.sol field order. +OFFER_ABI_TYPE = ( + "(" + "(address,(address,uint256,uint256,address)[],uint256,uint256,address,address)," + "bool,address,uint256,uint256,uint256,bytes32,address,bytes,address,address,bool,uint256,uint256" + ")" +) + + +def offer_tree_typehash(height): + if not 0 <= height <= 20: + raise ValueError(f"offer-tree height out of range: {height}") + return bytes.fromhex(OFFER_TREE_TYPE_HASHES[height]) + + +def _bytes32(v): + raw = bytes.fromhex(v.removeprefix("0x")) + assert len(raw) == 32, f"expected 32 bytes, got {len(raw)}" + return raw + + +def _hexbytes(v): + return bytes.fromhex(v.removeprefix("0x")) + + +# Returns the abi-encoded form of an Offer, ready for `abi.decode(bytes, (Offer))`. +def abi_encode_offer(o): + m = o["market"] + market = ( + w3.to_checksum_address(m["loanToken"]), + [ + ( + w3.to_checksum_address(cp["token"]), + int(cp["lltv"]), + int(cp["maxLif"]), + w3.to_checksum_address(cp["oracle"]), + ) + for cp in m["collateralParams"] + ], + int(m["maturity"]), + int(m["rcfThreshold"]), + w3.to_checksum_address(m["enterGate"]), + w3.to_checksum_address(m["liquidatorGate"]), + ) + offer = ( + market, + bool(o["buy"]), + w3.to_checksum_address(o["maker"]), + int(o["start"]), + int(o["expiry"]), + int(o["tick"]), + _bytes32(o["group"]), + w3.to_checksum_address(o["callback"]), + _hexbytes(o["callbackData"]), + w3.to_checksum_address(o["receiverIfMakerIsSeller"]), + w3.to_checksum_address(o["ratifier"]), + bool(o["reduceOnly"]), + int(o["maxUnits"]), + int(o["maxAssets"]), + ) + return "0x" + encode([OFFER_ABI_TYPE], [offer]).hex() + + +# Returns the hash of an offer (mirrors HashLib.hashOffer). +def hash_offer(o): + raw = bytes.fromhex(abi_encode_offer(o)[2:]) + return w3.to_hex(w3.solidity_keccak(["bytes"], [raw])) + + +# Returns the hash of a node given the hashes of its children. +def hash_node(left, right): + return w3.to_hex( + w3.solidity_keccak(["bytes32", "bytes32"], [_bytes32(left), _bytes32(right)]) + ) + + +# Builds a dense certificate from a power-of-two list of offers, in leftIndex order. +def build_dense(leaves, claimed_root): + n = len(leaves) + assert n > 0 and (n & (n - 1)) == 0, "dense leaves count must be a power of two" + + level = [hash_offer(o) for o in leaves] + while len(level) > 1: + level = [hash_node(level[2 * i], level[2 * i + 1]) for i in range(len(level) // 2)] + assert level[0].lower() == claimed_root.lower(), ( + f"dense: computed root {level[0]} != claimed root {claimed_root}" + ) + + return { + "mode": "dense", + "root": claimed_root, + "leafLength": n, + "leaf": [abi_encode_offer(o) for o in leaves], + } + + +# Builds a sparse certificate by walking each leaf's proof up to the root. +# Every sibling must resolve to another supplied leaf or a derivable internal node. +def build_sparse(entries, claimed_root): + nodes = {} + leaf_payloads = [] + + for entry in entries: + offer = entry["offer"] + idx = int(entry["leafIndex"]) + proof = entry["proof"] + leaf_hash = hash_offer(offer) + leaf_payloads.append((leaf_hash, offer)) + + current = leaf_hash + for i, sibling in enumerate(proof): + bit = (idx >> i) & 1 + left_id, right_id = (current, sibling) if bit == 0 else (sibling, current) + parent = hash_node(left_id, right_id) + nodes.setdefault(parent, (left_id, right_id)) + current = parent + assert current.lower() == claimed_root.lower(), ( + f"sparse: proof for leafIndex={idx} ends at {current}, not claimed root {claimed_root}" + ) + + leaf_ids = {h.lower() for (h, _) in leaf_payloads} + node_ids_lc = {n.lower() for n in nodes} + + for nid, (left_id, right_id) in nodes.items(): + for child_id, side in ((left_id, "left"), (right_id, "right")): + if child_id.lower() not in leaf_ids and child_id.lower() not in node_ids_lc: + raise ValueError( + f"sparse: {side} child {child_id} of internal node {nid} is neither a " + f"supplied leaf nor a derivable internal node." + ) + + emitted = set(leaf_ids) + pending = list(nodes.keys()) + ordered = [] + while pending: + next_pending = [] + progressed = False + for nid in pending: + left_id, right_id = nodes[nid] + if left_id.lower() in emitted and right_id.lower() in emitted: + ordered.append(nid) + emitted.add(nid.lower()) + progressed = True + else: + next_pending.append(nid) + if not progressed: + raise RuntimeError("topological sort failed; cycles or unresolved siblings") + pending = next_pending + + assert ordered[-1].lower() == claimed_root.lower(), ( + f"sparse: last emitted node {ordered[-1]} is not claimed root {claimed_root}" + ) + + return { + "mode": "sparse", + "root": claimed_root, + "leafLength": len(leaf_payloads), + "leaf": [abi_encode_offer(offer) for (_, offer) in leaf_payloads], + "nodeLength": len(ordered), + "node": [ + {"id": nid, "left": nodes[nid][0], "right": nodes[nid][1]} for nid in ordered + ], + } + + +# Reconstructs the EIP-712 digest for an OfferTree and either signs it locally +# (`signerKey`) or accepts a precomputed (signer, v, r, s). +def build_eip712(eip712_in, root, leaf_length): + ratifier = w3.to_checksum_address(eip712_in["ratifier"]) + chain_id = int(eip712_in["chainId"]) + height = (leaf_length - 1).bit_length() + if 1 << height != leaf_length: + raise ValueError( + f"eip712 requires a balanced tree; leafLength {leaf_length} is not a power of two" + ) + + struct_hash = w3.solidity_keccak( + ["bytes32", "bytes32"], [offer_tree_typehash(height), _bytes32(root)] + ) + domain_separator = w3.solidity_keccak( + ["bytes32", "uint256", "address"], [EIP712_DOMAIN_TYPEHASH, chain_id, ratifier] + ) + digest = w3.solidity_keccak( + ["bytes1", "bytes1", "bytes32", "bytes32"], + [b"\x19", b"\x01", domain_separator, struct_hash], + ) + + if "signerKey" in eip712_in: + signed = Account._sign_hash(digest, eip712_in["signerKey"]) + signer = Account.from_key(eip712_in["signerKey"]).address + v, r, s = signed.v, signed.r.to_bytes(32, "big"), signed.s.to_bytes(32, "big") + else: + signer = w3.to_checksum_address(eip712_in["signer"]) + v = int(eip712_in["v"]) + r = _bytes32(eip712_in["r"]) + s = _bytes32(eip712_in["s"]) + + return { + "ratifier": ratifier, + "chainId": chain_id, + "height": height, + "signer": signer, + "v": v, + "r": "0x" + r.hex(), + "s": "0x" + s.hex(), + } + + +def main(): + if len(sys.argv) != 2: + print("usage: python create_certificate.py ", file=sys.stderr) + sys.exit(2) + + with open(sys.argv[1]) as f: + proofs = json.load(f) + + mode = proofs["mode"] + root = proofs["root"] + if mode == "dense": + certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) + elif mode == "sparse": + certificate = build_sparse(proofs["leaves"], root) + else: + raise ValueError(f"unknown mode: {mode}") + + if "eip712" in proofs: + if mode != "dense": + raise ValueError("eip712 envelope is only supported for dense (balanced) trees") + certificate["eip712"] = build_eip712(proofs["eip712"], root, certificate["leafLength"]) + + with open("certificate.json", "w") as f: + json.dump(certificate, f, indent=2) + + +if __name__ == "__main__": + main() From 939a570f4af022b685b24594826c6438689be41e Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 26 May 2026 00:38:18 +0200 Subject: [PATCH 021/159] add checker --- foundry.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/foundry.toml b/foundry.toml index 1c268f0fd..5785fec1f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,6 +9,11 @@ fs_permissions = [{ access = "read", path = "test/ticks_exact.json" }] [profile.default.fmt] wrap_comments = true +[profile.checker] +test = "certora/checker" +match_contract = "Checker" +fs_permissions = [{ access = "read", path = "./" }] + [lint] exclude_lints = [ "asm-keccak256", From d9f174e5fd54d1119eb19206eafe52daccdc17b9 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 26 May 2026 00:38:50 +0200 Subject: [PATCH 022/159] summarise isRatify --- certora/specs/OfferTreeMembership.spec | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index dd1e00c45..b0548ce3b 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -14,14 +14,16 @@ methods { function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; + function Utils.callbackSuccess() external returns (bytes32) envfree; // Align the merkle verification and the helper's well-formedness on the same hash functions. function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); - // Take-side externals are irrelevant to merkle membership. `isRatified` is NONDET'd so the rule - // abstracts over the ratifier choice; the bridge to `Utils.isLeaf` is supplied in the rule body. - function _.isRatified(Midnight.Offer, bytes) external => NONDET; + // A successful ratifier must witness a merkle proof for the offer's hash. The + // obligation is discharged in Ratification.spec/isRatifiedRequiresIsLeaf, which + // dispatches across all linked ratifier implementations. + function _.isRatified(Midnight.Offer offer, bytes) external => isRatifiedSummary(offer) expect bytes32; function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; function _.transferFrom(address, address, uint256) external => NONDET; @@ -45,6 +47,15 @@ function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { return Utils.hashNode(a, b); } +function isRatifiedSummary(Midnight.Offer offer) returns bytes32 { + bytes32 result; + bytes32 root; + uint256 leafIndex; + bytes32[] proof; + require result == Utils.callbackSuccess() => Utils.isLeaf(root, Utils.hashOffer(offer), leafIndex, proof); + return result; +} + /// SOUNDNESS /// /// If a root corresponds to a node of a well-formed offer-tree, a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. @@ -66,7 +77,7 @@ rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, byte /// TAKE-LEVEL LIFT /// /// Every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. -/// The `require Utils.isLeaf(...)` below is the bridge from take to the merkle check, justified by composition: take requires `isRatified(...) == CALLBACK_SUCCESS`, and both SetterRatifier and EcrecoverRatifier require HashLib.isLeaf to pass. +/// `require Utils.isLeaf(...)` binds the merkle witness to the specific (root, leafIndex, proof) used in the well-formedness premise; the take->ratifier->merkle composition is mechanised via the `isRatifiedSummary` above (obligation discharged in Ratification.spec/isRatifiedRequiresIsLeaf). rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; require OfferTree.getHash(node) == root, "root is the hash of node"; From fc758a3686c0332700e2165d5253eb0d9e240aec Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 26 May 2026 14:41:18 +0200 Subject: [PATCH 023/159] trimmed down to core properties --- certora/checker/Checker.sol | 179 +------------------------ certora/checker/create_certificate.py | 80 +---------- certora/confs/SetterRatification.conf | 23 ---- certora/helpers/OfferTree.sol | 8 -- certora/specs/OfferTreeMembership.spec | 19 --- certora/specs/SetterRatification.spec | 56 -------- 6 files changed, 4 insertions(+), 361 deletions(-) delete mode 100644 certora/confs/SetterRatification.conf delete mode 100644 certora/specs/SetterRatification.spec diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol index fe41dff06..c57021782 100644 --- a/certora/checker/Checker.sol +++ b/certora/checker/Checker.sol @@ -57,35 +57,6 @@ contract Checker is Test { assertEq(level[0], root, "dense: root mismatch"); } - // Internal nodes must be supplied in topological order (children before parents). - // The last id is taken as the root. - function _verifySparse( - Offer[] memory leaves, - bytes32[] memory nodeIds, - bytes32[] memory nodeLefts, - bytes32[] memory nodeRights, - bytes32 root - ) internal { - require(nodeIds.length == nodeLefts.length, "node arrays length mismatch"); - require(nodeIds.length == nodeRights.length, "node arrays length mismatch"); - require(nodeIds.length > 0, "no internal nodes"); - - OfferTree tree = new OfferTree(); - - for (uint256 i = 0; i < leaves.length; i++) { - bytes32 leafHash = HashLib.hashOffer(leaves[i]); - if (tree.isEmpty(leafHash)) tree.newLeaf(leaves[i]); - } - for (uint256 i = 0; i < nodeIds.length; i++) { - if (tree.isEmpty(nodeIds[i])) { - tree.newInternalNode(nodeIds[i], nodeLefts[i], nodeRights[i]); - } - } - - bytes32 rootId = nodeIds[nodeIds.length - 1]; - assertEq(tree.getHash(rootId), root, "sparse: root mismatch"); - } - // Mirrors EcrecoverRatifier.isRatified: structHash wraps the offer-tree typehash // and root, the domain separator binds (chainId, ratifier), and the digest is the // standard EIP-712 form. @@ -120,7 +91,6 @@ contract Checker is Test { if (!vm.exists(path)) vm.skip(true, "no certificate.json at project root"); string memory json = vm.readFile(path); - string memory mode = json.readString(".mode"); bytes32 root = json.readBytes32(".root"); uint256 leafLength = json.readUint(".leafLength"); @@ -130,25 +100,8 @@ contract Checker is Test { leaves[i] = abi.decode(enc, (Offer)); } - bytes32 modeHash = keccak256(bytes(mode)); - if (modeHash == keccak256("dense")) { - _verifyDense(leaves, root); - _maybeVerifyEip712(json, root, leafLength); - } else if (modeHash == keccak256("sparse")) { - uint256 nodeLength = json.readUint(".nodeLength"); - bytes32[] memory ids = new bytes32[](nodeLength); - bytes32[] memory lefts = new bytes32[](nodeLength); - bytes32[] memory rights = new bytes32[](nodeLength); - for (uint256 i = 0; i < nodeLength; i++) { - string memory base = string.concat(".node[", vm.toString(i), "]"); - ids[i] = json.readBytes32(string.concat(base, ".id")); - lefts[i] = json.readBytes32(string.concat(base, ".left")); - rights[i] = json.readBytes32(string.concat(base, ".right")); - } - _verifySparse(leaves, ids, lefts, rights, root); - } else { - revert("unknown certificate mode"); - } + _verifyDense(leaves, root); + _maybeVerifyEip712(json, root, leafLength); } function testSyntheticDenseHeight2() public { @@ -193,22 +146,6 @@ contract Checker is Test { _verifyDense(leaves, root); } - function testSyntheticDenseHeight2AllEmpty() public { - Offer memory emptyOffer; - - Offer[] memory leaves = new Offer[](4); - leaves[0] = emptyOffer; - leaves[1] = emptyOffer; - leaves[2] = emptyOffer; - leaves[3] = emptyOffer; - - bytes32 hEmpty = HashLib.hashOffer(emptyOffer); - bytes32 inner = HashLib.hashNode(hEmpty, hEmpty); - bytes32 root = HashLib.hashNode(inner, inner); - - _verifyDense(leaves, root); - } - function testSyntheticEip712Height2() public { Offer[] memory leaves = new Offer[](4); for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); @@ -244,121 +181,11 @@ contract Checker is Test { ); } - function testSyntheticEip712DetectsSignerMismatch() public { - Offer[] memory leaves = new Offer[](2); - leaves[0] = _dummyOffer(300); - leaves[1] = _dummyOffer(301); - - bytes32 root = HashLib.hashNode(HashLib.hashOffer(leaves[0]), HashLib.hashOffer(leaves[1])); - - address ratifier = address(uint160(0xA17F1E7)); - uint256 chainId = 1; - uint256 height = 1; - - bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); - bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); - bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(uint256(0xB0B), digest); - - Eip712Envelope memory env = Eip712Envelope({ - ratifier: ratifier, - chainId: chainId, - height: height, - signer: vm.addr(uint256(0xDEADBEEF)), - v: v, - r: r, - s: s - }); - - vm.expectRevert(); - this.externalVerifyEip712(root, env); - } - - function testSyntheticEip712DetectsWrongRoot() public { - Offer[] memory leaves = new Offer[](2); - leaves[0] = _dummyOffer(400); - leaves[1] = _dummyOffer(401); - - bytes32 root = HashLib.hashNode(HashLib.hashOffer(leaves[0]), HashLib.hashOffer(leaves[1])); - - address ratifier = address(uint160(0xA17F1E7)); - uint256 chainId = 1; - uint256 height = 1; - uint256 privateKey = 0xC0FFEE; - - bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); - bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); - bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); - - Eip712Envelope memory env = Eip712Envelope({ - ratifier: ratifier, - chainId: chainId, - height: height, - signer: vm.addr(privateKey), - v: v, - r: r, - s: s - }); - - vm.expectRevert(); - this.externalVerifyEip712(keccak256(abi.encode(root, "tamper")), env); - } - - function testSyntheticSparseTwoLeaves() public { - Offer[] memory leaves = new Offer[](2); - leaves[0] = _dummyOffer(100); - leaves[1] = _dummyOffer(101); - - bytes32 leftHash = HashLib.hashOffer(leaves[0]); - bytes32 rightHash = HashLib.hashOffer(leaves[1]); - bytes32 root = HashLib.hashNode(leftHash, rightHash); - - bytes32[] memory ids = new bytes32[](1); - bytes32[] memory lefts = new bytes32[](1); - bytes32[] memory rights = new bytes32[](1); - ids[0] = root; - lefts[0] = leftHash; - rights[0] = rightHash; - - _verifySparse(leaves, ids, lefts, rights, root); - } - - function testSyntheticSparseDepth2OneActivePath() public { - Offer[] memory leaves = new Offer[](3); - leaves[0] = _dummyOffer(200); - leaves[1] = _dummyOffer(201); - leaves[2] = _dummyOffer(202); - - bytes32 h0 = HashLib.hashOffer(leaves[0]); - bytes32 h1 = HashLib.hashOffer(leaves[1]); - bytes32 hUncle = HashLib.hashOffer(leaves[2]); - bytes32 leftBranch = HashLib.hashNode(h0, h1); - bytes32 root = HashLib.hashNode(leftBranch, hUncle); - - bytes32[] memory ids = new bytes32[](2); - bytes32[] memory lefts = new bytes32[](2); - bytes32[] memory rights = new bytes32[](2); - - ids[0] = leftBranch; - lefts[0] = h0; - rights[0] = h1; - ids[1] = root; - lefts[1] = leftBranch; - rights[1] = hUncle; - - _verifySparse(leaves, ids, lefts, rights, root); - } - - // External wrappers so `vm.expectRevert` can catch internal-call reverts. + // External wrapper so `vm.expectRevert` can catch internal-call reverts. function externalVerifyDense(Offer[] memory leaves, bytes32 root) external { _verifyDense(leaves, root); } - function externalVerifyEip712(bytes32 root, Eip712Envelope memory env) external { - _verifyEip712(root, env); - } - // Distinct dummy offers, distinguished by `tick`. function _dummyOffer(uint256 nonce) internal pure returns (Offer memory o) { o.market.loanToken = address(uint160(0x1000 + nonce)); diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index 5982af4d7..0766ef8a9 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -126,82 +126,12 @@ def build_dense(leaves, claimed_root): ) return { - "mode": "dense", "root": claimed_root, "leafLength": n, "leaf": [abi_encode_offer(o) for o in leaves], } -# Builds a sparse certificate by walking each leaf's proof up to the root. -# Every sibling must resolve to another supplied leaf or a derivable internal node. -def build_sparse(entries, claimed_root): - nodes = {} - leaf_payloads = [] - - for entry in entries: - offer = entry["offer"] - idx = int(entry["leafIndex"]) - proof = entry["proof"] - leaf_hash = hash_offer(offer) - leaf_payloads.append((leaf_hash, offer)) - - current = leaf_hash - for i, sibling in enumerate(proof): - bit = (idx >> i) & 1 - left_id, right_id = (current, sibling) if bit == 0 else (sibling, current) - parent = hash_node(left_id, right_id) - nodes.setdefault(parent, (left_id, right_id)) - current = parent - assert current.lower() == claimed_root.lower(), ( - f"sparse: proof for leafIndex={idx} ends at {current}, not claimed root {claimed_root}" - ) - - leaf_ids = {h.lower() for (h, _) in leaf_payloads} - node_ids_lc = {n.lower() for n in nodes} - - for nid, (left_id, right_id) in nodes.items(): - for child_id, side in ((left_id, "left"), (right_id, "right")): - if child_id.lower() not in leaf_ids and child_id.lower() not in node_ids_lc: - raise ValueError( - f"sparse: {side} child {child_id} of internal node {nid} is neither a " - f"supplied leaf nor a derivable internal node." - ) - - emitted = set(leaf_ids) - pending = list(nodes.keys()) - ordered = [] - while pending: - next_pending = [] - progressed = False - for nid in pending: - left_id, right_id = nodes[nid] - if left_id.lower() in emitted and right_id.lower() in emitted: - ordered.append(nid) - emitted.add(nid.lower()) - progressed = True - else: - next_pending.append(nid) - if not progressed: - raise RuntimeError("topological sort failed; cycles or unresolved siblings") - pending = next_pending - - assert ordered[-1].lower() == claimed_root.lower(), ( - f"sparse: last emitted node {ordered[-1]} is not claimed root {claimed_root}" - ) - - return { - "mode": "sparse", - "root": claimed_root, - "leafLength": len(leaf_payloads), - "leaf": [abi_encode_offer(offer) for (_, offer) in leaf_payloads], - "nodeLength": len(ordered), - "node": [ - {"id": nid, "left": nodes[nid][0], "right": nodes[nid][1]} for nid in ordered - ], - } - - # Reconstructs the EIP-712 digest for an OfferTree and either signs it locally # (`signerKey`) or accepts a precomputed (signer, v, r, s). def build_eip712(eip712_in, root, leaf_length): @@ -253,18 +183,10 @@ def main(): with open(sys.argv[1]) as f: proofs = json.load(f) - mode = proofs["mode"] root = proofs["root"] - if mode == "dense": - certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) - elif mode == "sparse": - certificate = build_sparse(proofs["leaves"], root) - else: - raise ValueError(f"unknown mode: {mode}") + certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) if "eip712" in proofs: - if mode != "dense": - raise ValueError("eip712 envelope is only supported for dense (balanced) trees") certificate["eip712"] = build_eip712(proofs["eip712"], root, certificate["leafLength"]) with open("certificate.json", "w") as f: diff --git a/certora/confs/SetterRatification.conf b/certora/confs/SetterRatification.conf deleted file mode 100644 index 61dea9691..000000000 --- a/certora/confs/SetterRatification.conf +++ /dev/null @@ -1,23 +0,0 @@ -{ - "files": [ - "src/Midnight.sol", - "src/ratifiers/SetterRatifier.sol", - "certora/helpers/OfferTree.sol", - "certora/helpers/Utils.sol" - ], - "verify": "Midnight:certora/specs/SetterRatification.spec", - "solc": "solc-0.8.34", - "solc_via_ir": true, - "solc_evm_version": "osaka", - "optimistic_loop": true, - "loop_iter": 3, - "optimistic_hashing": true, - "hashing_length_bound": 1024, - "rule_sanity": "basic", - "smt_timeout": 7200, - "prover_args": [ - "-splitParallel true", - "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" - ], - "msg": "SetterRatification" -} diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 4024829d4..03f329363 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -63,14 +63,6 @@ contract OfferTree { return tree[id].left == 0 && tree[id].right == 0 && tree[id].hashNode != 0; } - function getLeft(bytes32 id) public view returns (bytes32) { - return tree[id].left; - } - - function getRight(bytes32 id) public view returns (bytes32) { - return tree[id].right; - } - // The specification of a well-formed tree is the following: // - empty nodes (left == 0 && right == 0 && hashNode == 0) are well-formed // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == hashOffer(offer) and id == hashNode diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index b0548ce3b..fdebf2b1b 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -73,22 +73,3 @@ rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, byte assert OfferTree.isLeafNode(leafId); } - -/// TAKE-LEVEL LIFT /// - -/// Every successful Midnight.take is for an offer registered as a leaf in the maker's offer-tree. -/// `require Utils.isLeaf(...)` binds the merkle witness to the specific (root, leafIndex, proof) used in the well-formedness premise; the take->ratifier->merkle composition is mechanised via the `isRatifiedSummary` above (obligation discharged in Ratification.spec/isRatifiedRequiresIsLeaf). -rule takeImpliesLeafInTree(env e, uint256 units, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, Midnight.Offer offer, bytes ratifierData, bytes32 root, uint256 leafIndex, bytes32[] proof) { - bytes32 node; - require OfferTree.getHash(node) == root, "root is the hash of node"; - require root != to_bytes32(0), "root is non-zero"; - - OfferTree.wellFormedPath(node, leafIndex, proof); - - bytes32 leafId = Utils.hashOffer(offer); - require Utils.isLeaf(root, leafId, leafIndex, proof); - - take(e, offer, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData, ratifierData); - - assert OfferTree.isLeafNode(leafId); -} diff --git a/certora/specs/SetterRatification.spec b/certora/specs/SetterRatification.spec deleted file mode 100644 index 06c4b7c72..000000000 --- a/certora/specs/SetterRatification.spec +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -// Copyright (c) 2025 Morpho Association - -using OfferTree as OfferTree; -using Utils as Utils; -using SetterRatifier as SetterRatifier; - -methods { - function OfferTree.getHash(bytes32) external returns (bytes32) envfree; - function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; - function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; - function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bytes32) envfree; - - function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; - function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; - function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - - function SetterRatifier.isRootRatified(address, bytes32) external returns (bool) envfree; - - // Align the merkle verification and the helper's well-formedness on the same hash functions. - // Routing through Utils (`keccak256(abi.encode(...))`) lets Certora's bounded-hash recognition - // supply injectivity automatically, instead of needing a ghost + axiom. - function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); -} - -function summaryHashOffer(Midnight.Offer offer) returns bytes32 { - return Utils.hashOffer(offer); -} - -function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { - return Utils.hashNode(a, b); -} - -// SetterRatifier-specific framing of takeCorrectness. -// Premise: the maker has explicitly committed to `root` via SetterRatifier.setIsRootRatified. Conclusion: every offer whose hash verifies against `root` via merkle proof is registered as a leaf in the maker's committed offer-tree. -rule setterRatifiedTakeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { - bytes32 node; - - // Assume that the maker has explicitly committed to root via SetterRatifier. - require SetterRatifier.isRootRatified(offer.maker, root); - - // Assume that root is the hash of node in the maker's tree. - require OfferTree.getHash(node) == root; - require root != to_bytes32(0); - - // Assume that the tree is well-formed along the proof path from node down to a leaf. - OfferTree.wellFormedPath(node, leafIndex, proof); - - // Compute the leaf hash once so both uses below bind to the same symbolic value. - bytes32 leafId = Utils.hashOffer(offer); - - require Utils.isLeaf(root, leafId, leafIndex, proof); - - assert OfferTree.isLeafNode(leafId); -} From 253e37e14cbc19ba8b4a1bf4686634e5d44a8e1d Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 29 May 2026 16:23:18 +0200 Subject: [PATCH 024/159] removed completeness --- certora/helpers/Utils.sol | 11 +++++-- certora/specs/OfferTreeMembership.spec | 45 +------------------------- certora/specs/Ratification.spec | 9 ++++++ 3 files changed, 18 insertions(+), 47 deletions(-) diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index 1f8aa03d0..fa557338d 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -15,15 +15,20 @@ import { contract Utils { function hashMarket(Market memory market) external pure returns (bytes32) { - return keccak256(abi.encode(market)); + return HashLib.hashMarket(market); } + // Wraps `HashLib.hashOffer` directly so CVL specs can expose the real EIP-712 offer hash + // envfree. Avoids the prior `keccak256(abi.encode(offer))` reimplementation, which is a + // *different* hash than `HashLib.hashOffer` (no typehash prefix, no inner hashing of + // market/callbackData) and broke keccak unification across summary boundaries when the + // prover had to forward-compute the merkle chain (completeness direction). function hashOffer(Offer memory offer) external pure returns (bytes32) { - return keccak256(abi.encode(offer)); + return HashLib.hashOffer(offer); } function hashNode(bytes32 a, bytes32 b) external pure returns (bytes32) { - return keccak256(abi.encode(a, b)); + return HashLib.hashNode(a, b); } function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index fdebf2b1b..9c3cf014b 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -4,62 +4,19 @@ using OfferTree as OfferTree; using Utils as Utils; methods { - function isAuthorized(address, address) external returns (bool) envfree; - function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; - function OfferTree.isWellFormed(bytes32) external returns (bool) envfree; function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; - function Utils.hashNode(bytes32, bytes32) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - function Utils.callbackSuccess() external returns (bytes32) envfree; - - // Align the merkle verification and the helper's well-formedness on the same hash functions. - function HashLib.hashOffer(Midnight.Offer memory offer) internal returns (bytes32) => summaryHashOffer(offer); - function HashLib.hashNode(bytes32 a, bytes32 b) internal returns (bytes32) => summaryHashNode(a, b); - - // A successful ratifier must witness a merkle proof for the offer's hash. The - // obligation is discharged in Ratification.spec/isRatifiedRequiresIsLeaf, which - // dispatches across all linked ratifier implementations. - function _.isRatified(Midnight.Offer offer, bytes) external => isRatifiedSummary(offer) expect bytes32; - function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; - function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; - function _.transferFrom(address, address, uint256) external => NONDET; - function _.transfer(address, uint256) external => NONDET; - function multicall(bytes[]) external => HAVOC_ALL DELETE; - function IdLib.toId(Midnight.Market memory, uint256, address) internal returns (bytes32) => NONDET; - function UtilsLib.mulDivDown(uint256, uint256, uint256) internal returns (uint256) => NONDET; - function UtilsLib.mulDivUp(uint256, uint256, uint256) internal returns (uint256) => NONDET; - function UtilsLib.msb(uint128) internal returns (uint256) => NONDET; - function UtilsLib.countBits(uint128) internal returns (uint256) => NONDET; - function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; - function isHealthy(Midnight.Market memory, bytes32, address) internal returns (bool) => NONDET; - function tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; -} - -function summaryHashOffer(Midnight.Offer offer) returns bytes32 { - return Utils.hashOffer(offer); -} - -function summaryHashNode(bytes32 a, bytes32 b) returns bytes32 { - return Utils.hashNode(a, b); -} -function isRatifiedSummary(Midnight.Offer offer) returns bytes32 { - bytes32 result; - bytes32 root; - uint256 leafIndex; - bytes32[] proof; - require result == Utils.callbackSuccess() => Utils.isLeaf(root, Utils.hashOffer(offer), leafIndex, proof); - return result; } /// SOUNDNESS /// /// If a root corresponds to a node of a well-formed offer-tree, a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. -rule takeCorrectness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { +rule membershipSoundness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; require OfferTree.getHash(node) == root, "root is the hash of node"; require root != to_bytes32(0), "root is non-zero"; diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index 9430ad465..fe3e27fa4 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -86,3 +86,12 @@ rule isRatifiedRequiresIsLeaf(env e, address ratifierAddr, Midnight.Offer offer, assert isLeafReturnedTrue, "ratifier must have called HashLib.isLeaf that returned true"; } + +/// Every successful Midnight.take implies HashLib.isLeaf was invoked and returned true. +rule takeRequiresIsLeaf(env e, Midnight.Offer offer, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData, bytes ratifierData) { + require !isLeafReturnedTrue, "fresh capture state"; + + take(e, offer, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData, ratifierData); + + assert isLeafReturnedTrue, "take must have triggered a ratifier that called HashLib.isLeaf returning true"; +} From 89c39d69c92cebd54fddeea356850372accfa424 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 1 Jun 2026 10:00:18 +0200 Subject: [PATCH 025/159] comment style adapted to URD --- certora/helpers/OfferTree.sol | 23 +++++++++++++++-------- certora/specs/OfferTreeMembership.spec | 26 +++++++++++++++++--------- certora/specs/OfferTreeWellFormed.spec | 11 ++++++----- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 03f329363..a3bd4ea33 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -5,20 +5,26 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; -// Trees are built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by construction. -// Leaves carry the offer payload so `isWellFormed` can pin a leaf's `hashNode` into the image of -// `hashOffer` (distinct keccak input shape from `hashNode`), giving domain separation against internal-node -// hashes for free under Certora's keccak model. contract OfferTree { struct Node { bytes32 left; bytes32 right; Offer offer; + // hash of the offer for leaves, and of [left.hash, right.hash] for internal nodes. bytes32 hashNode; } /* STORAGE */ + // The tree has no root because every node (and the nodes underneath) form an offer tree. + // We use bytes32 as keys of the mapping so that leaves can have an identifier that is the hash of the offer. + // This ensures that the same offer does not appear twice as a leaf in the tree. + // For internal nodes the key is left arbitrary, so that the certificate generation can choose freely any bytes32 + // value (that is not already used). + // Leaves keep their offer payload so that `isWellFormed` can recompute `hashOffer` and pin a leaf's `hashNode` into + // the image of `hashOffer`. Because `hashOffer` and `hashNode` feed keccak distinct input shapes, this gives domain + // separation between leaves and internal nodes for free under Certora's keccak model. + // The tree is built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by construction. mapping(bytes32 => Node) internal tree; /* MAIN FUNCTIONS */ @@ -63,11 +69,12 @@ contract OfferTree { return tree[id].left == 0 && tree[id].right == 0 && tree[id].hashNode != 0; } + // The specification of a well-formed tree is the following: - // - empty nodes (left == 0 && right == 0 && hashNode == 0) are well-formed - // - leaves (left == 0 && right == 0 && hashNode != 0) require hashNode == hashOffer(offer) and id == hashNode - // - internal nodes (left != 0 && right != 0) require non-empty children and hashNode = hashNode(left.hashNode, - // right.hashNode) - any other field combination is malformed + // - empty nodes are well-formed + // - leaves have the correct identifier and hashing + // - internal nodes have the correct hashing + // - internal nodes have exactly two non-empty children function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 9c3cf014b..b8d1abcda 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -10,23 +10,31 @@ methods { function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; - } -/// SOUNDNESS /// - -/// If a root corresponds to a node of a well-formed offer-tree, a successful merkle verification of the offer's hash against that root implies the offer is registered as a leaf in the tree. +// The main correctness result of the verification. +// It ensures that if the root is setup according to a well-formed offer tree, then a successful Merkle verification of an offer against that root implies the offer is registered as a leaf in the tree. rule membershipSoundness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; - require OfferTree.getHash(node) == root, "root is the hash of node"; - require root != to_bytes32(0), "root is non-zero"; + // Assume that root is the hash of node in the tree. + require OfferTree.getHash(node) == root; + + // Assume that the root is non-zero, otherwise empty nodes would hash-match it. + require root != to_bytes32(0); + + // No need to make sure that node is equal to the root: one can pass an internal node instead. + // Assume that the tree is well-formed along the path down to the leaf. OfferTree.wellFormedPath(node, leafIndex, proof); - // Compute leafId once so both uses below bind to the same symbolic hash. + // Compute the leaf identifier once so both uses below bind to the same hash. bytes32 leafId = Utils.hashOffer(offer); - require leafId != to_bytes32(0), "leafId is non-zero"; - require Utils.isLeaf(root, leafId, leafIndex, proof), "merkle proof verifies"; + + // Assume that the leaf identifier is non-zero, matching the constraint enforced by newLeaf. + require leafId != to_bytes32(0); + + // Assume that the Merkle proof verifies the offer's hash against the root. + require Utils.isLeaf(root, leafId, leafIndex, proof); assert OfferTree.isLeafNode(leafId); } diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index c584c5cd6..50b0f4380 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -5,13 +5,14 @@ methods { function isWellFormed(bytes32) external returns (bool) envfree; } +// The zero node is empty, so it can serve as the canonical empty child of every node in the tree. strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); +// Every node of the tree is well-formed, which is what makes the membership result in OfferTreeMembership.spec sound. strong invariant wellFormed(bytes32 id) isWellFormed(id) - { - preserved { - requireInvariant zeroIsEmpty(); - } - } +{ preserved { + requireInvariant zeroIsEmpty(); + } +} From a43f97de4060be479262b758929fd626303610f4 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 1 Jun 2026 14:44:09 +0200 Subject: [PATCH 026/159] retained only testVerifyCertificate in Checker; split offer into static and dynamic part --- certora/checker/Checker.sol | 155 ++++++------------------- certora/checker/create_certificate.py | 140 +++++++++++++++++++--- certora/helpers/OfferTree.sol | 89 ++++++++++++-- certora/specs/OfferTreeWellFormed.spec | 29 ++++- 4 files changed, 263 insertions(+), 150 deletions(-) diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol index c57021782..57dd646a0 100644 --- a/certora/checker/Checker.sol +++ b/certora/checker/Checker.sol @@ -6,7 +6,7 @@ import {Test} from "../../lib/forge-std/src/Test.sol"; import {stdJson} from "../../lib/forge-std/src/StdJson.sol"; import {OfferTree} from "../helpers/OfferTree.sol"; -import {Offer, Market, CollateralParams} from "../../src/interfaces/IMidnight.sol"; +import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; import {EIP712_DOMAIN_TYPEHASH} from "../../src/ratifiers/interfaces/IEcrecoverRatifier.sol"; @@ -23,54 +23,48 @@ contract Checker is Test { bytes32 s; } - // Rebuild a dense tree level-by-level via the verified `newLeaf` and - // `newInternalNode` primitives and assert the top hash matches `root`. - // Inserts are skipped when the target slot is already populated, so duplicate - // leaves (e.g. an `emptyOffer` repeated across padding slots) collapse into a - // single helper slot. - function _verifyDense(Offer[] memory leaves, bytes32 root) internal { + struct InternalNode { + bytes32 id; + bytes32 left; + bytes32 right; + } + + // Replay the certificate through the verified `newLeaf` and `newInternalNode` + // primitives, then assert that the final certificate item matches `root`. + function _verifyCertificate(Offer[] memory leaves, InternalNode[] memory nodes, bytes32 root) internal { require(leaves.length > 0, "no leaves"); - require((leaves.length & (leaves.length - 1)) == 0, "leaves length not power of two"); + require(nodes.length > 0 || leaves.length == 1, "missing internal nodes"); OfferTree tree = new OfferTree(); - bytes32[] memory level = new bytes32[](leaves.length); for (uint256 i = 0; i < leaves.length; i++) { - bytes32 leafHash = HashLib.hashOffer(leaves[i]); - if (tree.isEmpty(leafHash)) tree.newLeaf(leaves[i]); - level[i] = leafHash; + tree.newLeaf(leaves[i]); } - while (level.length > 1) { - uint256 half = level.length / 2; - bytes32[] memory next = new bytes32[](half); - for (uint256 i = 0; i < half; i++) { - bytes32 leftHash = level[2 * i]; - bytes32 rightHash = level[2 * i + 1]; - bytes32 nodeHash = HashLib.hashNode(leftHash, rightHash); - if (tree.isEmpty(nodeHash)) tree.newInternalNode(nodeHash, leftHash, rightHash); - next[i] = nodeHash; - } - level = next; + bytes32 rootId = HashLib.hashOffer(leaves[0]); + for (uint256 i = 0; i < nodes.length; i++) { + InternalNode memory node = nodes[i]; + tree.newInternalNode(node.id, node.left, node.right); + rootId = node.id; } - assertEq(level[0], root, "dense: root mismatch"); + assertTrue(!tree.isEmpty(rootId), "empty root"); + assertEq(tree.getHash(rootId), root, "mismatched roots"); } // Mirrors EcrecoverRatifier.isRatified: structHash wraps the offer-tree typehash // and root, the domain separator binds (chainId, ratifier), and the digest is the // standard EIP-712 form. - function _verifyEip712(bytes32 root, Eip712Envelope memory env) internal { + function _verifyEip712(bytes32 root, Eip712Envelope memory env) internal pure { bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(env.height), root)); - bytes32 domainSeparator = - keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, env.chainId, env.ratifier)); + bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, env.chainId, env.ratifier)); bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); address recovered = ecrecover(digest, env.v, env.r, env.s); require(recovered != address(0), "eip712: invalid signature"); assertEq(recovered, env.signer, "eip712: signer mismatch"); } - function _maybeVerifyEip712(string memory json, bytes32 root, uint256 leafLength) internal { + function _maybeVerifyEip712(string memory json, bytes32 root) internal view { if (!json.keyExists(".eip712")) return; Eip712Envelope memory env; @@ -82,7 +76,9 @@ contract Checker is Test { env.r = json.readBytes32(".eip712.r"); env.s = json.readBytes32(".eip712.s"); - require(1 << env.height == leafLength, "eip712: height does not match leaf count"); + if (json.keyExists(".treeLeafLength")) { + require(1 << env.height == json.readUint(".treeLeafLength"), "eip712: height does not match leaf count"); + } _verifyEip712(root, env); } @@ -100,99 +96,14 @@ contract Checker is Test { leaves[i] = abi.decode(enc, (Offer)); } - _verifyDense(leaves, root); - _maybeVerifyEip712(json, root, leafLength); - } - - function testSyntheticDenseHeight2() public { - Offer[] memory leaves = new Offer[](4); - for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); - - bytes32 h0 = HashLib.hashOffer(leaves[0]); - bytes32 h1 = HashLib.hashOffer(leaves[1]); - bytes32 h2 = HashLib.hashOffer(leaves[2]); - bytes32 h3 = HashLib.hashOffer(leaves[3]); - bytes32 leftBranch = HashLib.hashNode(h0, h1); - bytes32 rightBranch = HashLib.hashNode(h2, h3); - bytes32 root = HashLib.hashNode(leftBranch, rightBranch); - - _verifyDense(leaves, root); - } - - function testSyntheticDenseHeight2DetectsRootMismatch() public { - Offer[] memory leaves = new Offer[](4); - for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); - - vm.expectRevert(); - this.externalVerifyDense(leaves, bytes32(uint256(0xdeadbeef))); - } - - function testSyntheticDenseHeight2WithEmptyPadding() public { - Offer memory emptyOffer; - Offer memory real = _dummyOffer(42); - - Offer[] memory leaves = new Offer[](4); - leaves[0] = real; - leaves[1] = emptyOffer; - leaves[2] = emptyOffer; - leaves[3] = emptyOffer; - - bytes32 hReal = HashLib.hashOffer(real); - bytes32 hEmpty = HashLib.hashOffer(emptyOffer); - bytes32 leftBranch = HashLib.hashNode(hReal, hEmpty); - bytes32 rightBranch = HashLib.hashNode(hEmpty, hEmpty); - bytes32 root = HashLib.hashNode(leftBranch, rightBranch); - - _verifyDense(leaves, root); - } - - function testSyntheticEip712Height2() public { - Offer[] memory leaves = new Offer[](4); - for (uint256 i = 0; i < 4; i++) leaves[i] = _dummyOffer(i); - - bytes32 h0 = HashLib.hashOffer(leaves[0]); - bytes32 h1 = HashLib.hashOffer(leaves[1]); - bytes32 h2 = HashLib.hashOffer(leaves[2]); - bytes32 h3 = HashLib.hashOffer(leaves[3]); - bytes32 root = HashLib.hashNode(HashLib.hashNode(h0, h1), HashLib.hashNode(h2, h3)); - - address ratifier = address(uint160(0xA17F1E7)); - uint256 chainId = 1; - uint256 height = 2; - uint256 privateKey = 0xA11CE; - - bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(height), root)); - bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)); - bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); - - _verifyDense(leaves, root); - _verifyEip712( - root, - Eip712Envelope({ - ratifier: ratifier, - chainId: chainId, - height: height, - signer: vm.addr(privateKey), - v: v, - r: r, - s: s - }) - ); - } - - // External wrapper so `vm.expectRevert` can catch internal-call reverts. - function externalVerifyDense(Offer[] memory leaves, bytes32 root) external { - _verifyDense(leaves, root); - } + uint256 nodeLength = json.readUint(".nodeLength"); + InternalNode[] memory nodes = new InternalNode[](nodeLength); + for (uint256 i = 0; i < nodeLength; i++) { + bytes memory enc = json.readBytes(string.concat(".node[", vm.toString(i), "]")); + nodes[i] = abi.decode(enc, (InternalNode)); + } - // Distinct dummy offers, distinguished by `tick`. - function _dummyOffer(uint256 nonce) internal pure returns (Offer memory o) { - o.market.loanToken = address(uint160(0x1000 + nonce)); - o.market.collateralParams = new CollateralParams[](0); - o.maker = address(uint160(0x2000 + nonce)); - o.tick = nonce; - o.maxUnits = 1; - o.maxAssets = 1; + _verifyCertificate(leaves, nodes, root); + _maybeVerifyEip712(json, root); } } diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index 0766ef8a9..a920cccd4 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -3,14 +3,23 @@ from eth_abi import encode from eth_account import Account -from web3 import EthereumTesterProvider, Web3 +from web3 import Web3 -w3 = Web3(EthereumTesterProvider()) +w3 = Web3() # keccak256("EIP712Domain(uint256 chainId,address verifyingContract)"). EIP712_DOMAIN_TYPEHASH = bytes.fromhex( "47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218" ) +COLLATERAL_PARAMS_TYPEHASH = bytes.fromhex( + "af44a88eb50ebdbbebd980e5a23045c44f61ece5f80ab708a1bbe8718102e6af" +) +MARKET_TYPEHASH = bytes.fromhex( + "358117e98511cc3df97175dca58053b06675b43ad090b0553f8a1eff008b6e2e" +) +OFFER_TYPEHASH = bytes.fromhex( + "980a4cfc9766df84667f316d76e10cefc8caf04fb4cd4a9fca00a8e7b34f619c" +) # Precomputed offerTreeTypeHash(h) for h in 0..20; mirrors HashLib.offerTreeTypeHash. OFFER_TREE_TYPE_HASHES = [ @@ -44,6 +53,7 @@ "bool,address,uint256,uint256,uint256,bytes32,address,bytes,address,address,bool,uint256,uint256" ")" ) +INTERNAL_NODE_ABI_TYPE = "(bytes32,bytes32,bytes32)" def offer_tree_typehash(height): @@ -62,6 +72,10 @@ def _hexbytes(v): return bytes.fromhex(v.removeprefix("0x")) +def _keccak_abi(types, values): + return w3.keccak(encode(types, values)) + + # Returns the abi-encoded form of an Offer, ready for `abi.decode(bytes, (Offer))`. def abi_encode_offer(o): m = o["market"] @@ -100,17 +114,88 @@ def abi_encode_offer(o): return "0x" + encode([OFFER_ABI_TYPE], [offer]).hex() +def abi_encode_node(node_id, left, right): + node = (_bytes32(node_id), _bytes32(left), _bytes32(right)) + return "0x" + encode([INTERNAL_NODE_ABI_TYPE], [node]).hex() + + +def hash_collateral_params(cp): + return _keccak_abi( + ["bytes32", "address", "uint256", "uint256", "address"], + [ + COLLATERAL_PARAMS_TYPEHASH, + w3.to_checksum_address(cp["token"]), + int(cp["lltv"]), + int(cp["maxLif"]), + w3.to_checksum_address(cp["oracle"]), + ], + ) + + +def hash_market(m): + collateral_params_hashes = b"".join( + hash_collateral_params(cp) for cp in m["collateralParams"] + ) + collateral_params_hash = w3.keccak(collateral_params_hashes) + return _keccak_abi( + ["bytes32", "address", "bytes32", "uint256", "uint256", "address", "address"], + [ + MARKET_TYPEHASH, + w3.to_checksum_address(m["loanToken"]), + collateral_params_hash, + int(m["maturity"]), + int(m["rcfThreshold"]), + w3.to_checksum_address(m["enterGate"]), + w3.to_checksum_address(m["liquidatorGate"]), + ], + ) + + # Returns the hash of an offer (mirrors HashLib.hashOffer). def hash_offer(o): - raw = bytes.fromhex(abi_encode_offer(o)[2:]) - return w3.to_hex(w3.solidity_keccak(["bytes"], [raw])) + return w3.to_hex( + _keccak_abi( + [ + "bytes32", + "bytes32", + "bool", + "address", + "uint256", + "uint256", + "uint256", + "bytes32", + "address", + "bytes32", + "address", + "address", + "bool", + "uint256", + "uint256", + ], + [ + OFFER_TYPEHASH, + hash_market(o["market"]), + bool(o["buy"]), + w3.to_checksum_address(o["maker"]), + int(o["start"]), + int(o["expiry"]), + int(o["tick"]), + _bytes32(o["group"]), + w3.to_checksum_address(o["callback"]), + w3.keccak(_hexbytes(o["callbackData"])), + w3.to_checksum_address(o["receiverIfMakerIsSeller"]), + w3.to_checksum_address(o["ratifier"]), + bool(o["reduceOnly"]), + int(o["maxUnits"]), + int(o["maxAssets"]), + ], + ) + ) # Returns the hash of a node given the hashes of its children. def hash_node(left, right): - return w3.to_hex( - w3.solidity_keccak(["bytes32", "bytes32"], [_bytes32(left), _bytes32(right)]) - ) + return w3.to_hex(w3.keccak(_bytes32(left) + _bytes32(right))) # Builds a dense certificate from a power-of-two list of offers, in leftIndex order. @@ -118,17 +203,41 @@ def build_dense(leaves, claimed_root): n = len(leaves) assert n > 0 and (n & (n - 1)) == 0, "dense leaves count must be a power of two" + leaf_instructions = {} + node_instructions = {} + level = [hash_offer(o) for o in leaves] + for leaf, leaf_hash in zip(leaves, level): + encoded_leaf = abi_encode_offer(leaf) + previous = leaf_instructions.setdefault(leaf_hash, encoded_leaf) + assert previous == encoded_leaf, "leaf hash collides with a different offer" + while len(level) > 1: - level = [hash_node(level[2 * i], level[2 * i + 1]) for i in range(len(level) // 2)] + next_level = [] + for i in range(len(level) // 2): + left = level[2 * i] + right = level[2 * i + 1] + node_hash = hash_node(left, right) + assert ( + node_hash not in leaf_instructions + ), "internal node id collides with a leaf id" + encoded_node = abi_encode_node(node_hash, left, right) + previous = node_instructions.setdefault(node_hash, encoded_node) + assert previous == encoded_node, "internal node id collides with different children" + next_level.append(node_hash) + level = next_level + assert level[0].lower() == claimed_root.lower(), ( f"dense: computed root {level[0]} != claimed root {claimed_root}" ) return { "root": claimed_root, - "leafLength": n, - "leaf": [abi_encode_offer(o) for o in leaves], + "treeLeafLength": n, + "leafLength": len(leaf_instructions), + "leaf": list(leaf_instructions.values()), + "nodeLength": len(node_instructions), + "node": list(node_instructions.values()), } @@ -143,16 +252,13 @@ def build_eip712(eip712_in, root, leaf_length): f"eip712 requires a balanced tree; leafLength {leaf_length} is not a power of two" ) - struct_hash = w3.solidity_keccak( + struct_hash = _keccak_abi( ["bytes32", "bytes32"], [offer_tree_typehash(height), _bytes32(root)] ) - domain_separator = w3.solidity_keccak( + domain_separator = _keccak_abi( ["bytes32", "uint256", "address"], [EIP712_DOMAIN_TYPEHASH, chain_id, ratifier] ) - digest = w3.solidity_keccak( - ["bytes1", "bytes1", "bytes32", "bytes32"], - [b"\x19", b"\x01", domain_separator, struct_hash], - ) + digest = w3.keccak(b"\x19\x01" + domain_separator + struct_hash) if "signerKey" in eip712_in: signed = Account._sign_hash(digest, eip712_in["signerKey"]) @@ -187,7 +293,7 @@ def main(): certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) if "eip712" in proofs: - certificate["eip712"] = build_eip712(proofs["eip712"], root, certificate["leafLength"]) + certificate["eip712"] = build_eip712(proofs["eip712"], root, certificate["treeLeafLength"]) with open("certificate.json", "w") as f: json.dump(certificate, f, indent=2) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index a3bd4ea33..939a89a73 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -3,13 +3,38 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; -import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; +import {HashLib, OFFER_TYPEHASH} from "../../src/ratifiers/libraries/HashLib.sol"; + +// A leaf's offer reaches `HashLib.hashOffer` only through fixed-size fields: every dynamic member of `Offer` +// (`market.collateralParams` and `callbackData`) is already reduced to a single `bytes32` before the final +// keccak (`hashMarket(market)` and `keccak256(callbackData)`). So we store that fixed-size pre-image instead +// of the raw `Offer`. This keeps every `Node` fixed-size, so `isWellFormed` re-hashes a leaf with one bounded +// keccak (no dynamic-array reads, no loops) — the property that lets the wellFormed invariant scale, exactly +// as it does for URD's fixed-size leaves. `_hashLeaf` mirrors `hashOffer`'s outer keccak field-for-field, so a +// leaf's id is the real `hashOffer` value; the wellFormed invariant's `newLeaf` case checks this mirror holds +// (`id == hashOffer(offer)` and `id == _hashLeaf(leaf)`), so the correspondence is verified, not assumed. +struct Leaf { + bytes32 marketHash; // = HashLib.hashMarket(offer.market) + bool buy; + address maker; + uint256 start; + uint256 expiry; + uint256 tick; + bytes32 group; + address callback; + bytes32 callbackDataHash; // = keccak256(offer.callbackData) + address receiverIfMakerIsSeller; + address ratifier; + bool reduceOnly; + uint256 maxUnits; + uint256 maxAssets; +} contract OfferTree { struct Node { bytes32 left; bytes32 right; - Offer offer; + Leaf leaf; // hash of the offer for leaves, and of [left.hash, right.hash] for internal nodes. bytes32 hashNode; } @@ -21,10 +46,11 @@ contract OfferTree { // This ensures that the same offer does not appear twice as a leaf in the tree. // For internal nodes the key is left arbitrary, so that the certificate generation can choose freely any bytes32 // value (that is not already used). - // Leaves keep their offer payload so that `isWellFormed` can recompute `hashOffer` and pin a leaf's `hashNode` into - // the image of `hashOffer`. Because `hashOffer` and `hashNode` feed keccak distinct input shapes, this gives domain - // separation between leaves and internal nodes for free under Certora's keccak model. - // The tree is built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by construction. + // Leaves keep the fixed-size pre-image of `hashOffer` (see `Leaf`) so `isWellFormed` can recompute a leaf's hash + // and pin its `hashNode` into the image of `hashOffer`. Because `hashOffer` and `hashNode` feed keccak distinct + // input shapes, this gives domain separation between leaves and internal nodes for free under Certora's keccak + // model. The tree is built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by + // construction. mapping(bytes32 => Node) internal tree; /* MAIN FUNCTIONS */ @@ -34,7 +60,22 @@ contract OfferTree { require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; require(_isEmpty(n), "leaf is not empty"); - n.offer = offer; + // Store the fixed-size pre-image of `hashOffer`; the dynamic members are kept only as their sub-hashes. + Leaf storage l = n.leaf; + l.marketHash = HashLib.hashMarket(offer.market); + l.buy = offer.buy; + l.maker = offer.maker; + l.start = offer.start; + l.expiry = offer.expiry; + l.tick = offer.tick; + l.group = offer.group; + l.callback = offer.callback; + l.callbackDataHash = keccak256(offer.callbackData); + l.receiverIfMakerIsSeller = offer.receiverIfMakerIsSeller; + l.ratifier = offer.ratifier; + l.reduceOnly = offer.reduceOnly; + l.maxUnits = offer.maxUnits; + l.maxAssets = offer.maxAssets; n.hashNode = id; } @@ -69,6 +110,38 @@ contract OfferTree { return tree[id].left == 0 && tree[id].right == 0 && tree[id].hashNode != 0; } + function hashOffer(Offer memory offer) public pure returns (bytes32) { + return HashLib.hashOffer(offer); + } + + function _hashLeaf(bytes32 id) public view returns (bytes32) { + return _hashLeaf(tree[id].leaf); + } + + // Recompute the leaf hash from its stored fixed-size pre-image. Mirrors `HashLib.hashOffer`'s outer keccak + // field-for-field, with `marketHash` standing in for `hashMarket(market)` and `callbackDataHash` for + // `keccak256(callbackData)`. Equals `HashLib.hashOffer(offer)` whenever the fields were extracted from `offer`. + function _hashLeaf(Leaf storage l) internal view returns (bytes32) { + return keccak256( + abi.encode( + OFFER_TYPEHASH, + l.marketHash, + l.buy, + l.maker, + l.start, + l.expiry, + l.tick, + l.group, + l.callback, + l.callbackDataHash, + l.receiverIfMakerIsSeller, + l.ratifier, + l.reduceOnly, + l.maxUnits, + l.maxAssets + ) + ); + } // The specification of a well-formed tree is the following: // - empty nodes are well-formed @@ -79,7 +152,7 @@ contract OfferTree { Node storage n = tree[id]; if (_isEmpty(n)) return true; if (n.left == 0 && n.right == 0) { - bytes32 expected = HashLib.hashOffer(n.offer); + bytes32 expected = _hashLeaf(n.leaf); return n.hashNode == expected && id == expected; } if (n.left != 0 && n.right != 0) { diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 50b0f4380..92c5cd575 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,6 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later +// No hashing summaries are needed: `Node` stores only the fixed-size pre-image of `hashOffer` (see OfferTree.sol), +// so `isWellFormed` re-hashes a leaf with a single bounded keccak over fixed-size storage — no dynamic-array reads, +// no loops. The only dynamic hashing is `newLeaf` hashing its offer argument once, which is cheap. + methods { + function newLeaf(OfferTree.Offer) external envfree; + function _hashLeaf(bytes32) external returns (bytes32) envfree; + function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; function isEmpty(bytes32) external returns (bool) envfree; function isWellFormed(bytes32) external returns (bool) envfree; } @@ -12,7 +19,23 @@ strong invariant zeroIsEmpty() // Every node of the tree is well-formed, which is what makes the membership result in OfferTreeMembership.spec sound. strong invariant wellFormed(bytes32 id) isWellFormed(id) -{ preserved { - requireInvariant zeroIsEmpty(); - } + { + preserved { + requireInvariant zeroIsEmpty(); + } + } + +// Focused bridge check: `newLeaf` keys the node by `HashLib.hashOffer(offer)` and stores the fixed-size +// pre-image that `_hashLeaf` re-hashes. This rule catches drift between `_hashLeaf` and the real offer hash +// construction. +rule newLeafConnectsHashLeafToHashOffer(OfferTree.Offer offer) { + bytes32 id = hashOffer(offer); + + require id != to_bytes32(0); + require isEmpty(id); + + newLeaf(offer); + + assert _hashLeaf(id) == id; + assert _hashLeaf(id) == hashOffer(offer); } From 65e69d19b7186d4235671004e06b1ccd2bb275b5 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 1 Jun 2026 15:11:19 +0200 Subject: [PATCH 027/159] removed ratifier --- certora/checker/Checker.sol | 42 -------------- certora/checker/create_certificate.py | 79 --------------------------- 2 files changed, 121 deletions(-) diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol index 57dd646a0..1a5e4445f 100644 --- a/certora/checker/Checker.sol +++ b/certora/checker/Checker.sol @@ -8,21 +8,10 @@ import {stdJson} from "../../lib/forge-std/src/StdJson.sol"; import {OfferTree} from "../helpers/OfferTree.sol"; import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; -import {EIP712_DOMAIN_TYPEHASH} from "../../src/ratifiers/interfaces/IEcrecoverRatifier.sol"; contract Checker is Test { using stdJson for string; - struct Eip712Envelope { - address ratifier; - uint256 chainId; - uint256 height; - address signer; - uint8 v; - bytes32 r; - bytes32 s; - } - struct InternalNode { bytes32 id; bytes32 left; @@ -52,36 +41,6 @@ contract Checker is Test { assertEq(tree.getHash(rootId), root, "mismatched roots"); } - // Mirrors EcrecoverRatifier.isRatified: structHash wraps the offer-tree typehash - // and root, the domain separator binds (chainId, ratifier), and the digest is the - // standard EIP-712 form. - function _verifyEip712(bytes32 root, Eip712Envelope memory env) internal pure { - bytes32 structHash = keccak256(abi.encode(HashLib.offerTreeTypeHash(env.height), root)); - bytes32 domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, env.chainId, env.ratifier)); - bytes32 digest = keccak256(bytes.concat(hex"1901", domainSeparator, structHash)); - address recovered = ecrecover(digest, env.v, env.r, env.s); - require(recovered != address(0), "eip712: invalid signature"); - assertEq(recovered, env.signer, "eip712: signer mismatch"); - } - - function _maybeVerifyEip712(string memory json, bytes32 root) internal view { - if (!json.keyExists(".eip712")) return; - - Eip712Envelope memory env; - env.ratifier = json.readAddress(".eip712.ratifier"); - env.chainId = json.readUint(".eip712.chainId"); - env.height = json.readUint(".eip712.height"); - env.signer = json.readAddress(".eip712.signer"); - env.v = uint8(json.readUint(".eip712.v")); - env.r = json.readBytes32(".eip712.r"); - env.s = json.readBytes32(".eip712.s"); - - if (json.keyExists(".treeLeafLength")) { - require(1 << env.height == json.readUint(".treeLeafLength"), "eip712: height does not match leaf count"); - } - _verifyEip712(root, env); - } - function testVerifyCertificate() public { string memory path = string.concat(vm.projectRoot(), "/certificate.json"); if (!vm.exists(path)) vm.skip(true, "no certificate.json at project root"); @@ -104,6 +63,5 @@ contract Checker is Test { } _verifyCertificate(leaves, nodes, root); - _maybeVerifyEip712(json, root); } } diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index a920cccd4..34a99eb30 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -2,15 +2,10 @@ import sys from eth_abi import encode -from eth_account import Account from web3 import Web3 w3 = Web3() -# keccak256("EIP712Domain(uint256 chainId,address verifyingContract)"). -EIP712_DOMAIN_TYPEHASH = bytes.fromhex( - "47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218" -) COLLATERAL_PARAMS_TYPEHASH = bytes.fromhex( "af44a88eb50ebdbbebd980e5a23045c44f61ece5f80ab708a1bbe8718102e6af" ) @@ -21,31 +16,6 @@ "980a4cfc9766df84667f316d76e10cefc8caf04fb4cd4a9fca00a8e7b34f619c" ) -# Precomputed offerTreeTypeHash(h) for h in 0..20; mirrors HashLib.offerTreeTypeHash. -OFFER_TREE_TYPE_HASHES = [ - "2b9ee710e1977dfc5778fe18c905ccc1d9e144baf3ba83be732d4da65ecb73e3", - "3cc16189b92a85898f1d5c6e87282c8ded7c1c93b2323d5e85ae10c5f4b2b220", - "6de37d3e570afa293a8107d4b6b1d9547616c04f42164d009c89194787b2ffa6", - "ba3ea2ddfbf40a906fcd1b9506dbd344c062e8dcba8b5c902ceb13339f45a358", - "e5faa865e93bc1b7b8fdf91980f54682d649683b014edd6c54b642f5a0c96977", - "eda50f61dd2a827c6ff9fbfcd54335628dcaa78aaa4f2d118c60886219cdce2b", - "54e2c9cc40cdc0e9ad530cf2be298f952f57af2b18b02f88274a9bbab359d23a", - "c9d81859d60d6b21c688f4be93ca83e3be222728bb156ef5f4cf497f879f1e29", - "d59b0c4544e0c60c8611eab0aaa402575f14ee784d22289c5d57f48c422a62d6", - "ccad21701f34f08bb8398a3dbc77e20e4c9c424930f3a8b31485bf059e2bdb20", - "8a42dfb49807647bfc49c906aef322aa0239d40e4cb675761e141bc7bfa530da", - "2adc0d948b2e3ecb642661590d2eec36d4e71e9acf382deb6574371800caf198", - "f5845dfaed016de272342f346346a49d4b1694f622144d420558a38e46ac9dad", - "3d7df854e6294bf433b64bbb8d0a82fa875a87b45b0016db27fc5752e54126ad", - "72a991a101708716ff427c524404ab44f4d4d1f4e7e76c0ae8b967222164b348", - "762c88fc52cf78a54401d247790f1bdb619d51d3458d1415c20d1422197cecc4", - "8ede2209e94c8d5f8379d733dc8712b71a3888c1c4b70f3d6b22285f70bf4286", - "425b18f07b3ac2f641977d2c294590565dd40b5d8414610568dca64628399975", - "7e7d98718c0180e882e5963b9bd49810096912c273dfa38d8afdd6d39fde86ec", - "8d35d491a29d846489e19688efff3c4cc7dbd54458058d49b30294074539f0b9", - "824e385eea1953bcbc783bf900b18aa6fba129b6908765e986cf0968b491ec4f", -] - # ABI signature for `Offer` matching src/interfaces/IMidnight.sol field order. OFFER_ABI_TYPE = ( "(" @@ -56,12 +26,6 @@ INTERNAL_NODE_ABI_TYPE = "(bytes32,bytes32,bytes32)" -def offer_tree_typehash(height): - if not 0 <= height <= 20: - raise ValueError(f"offer-tree height out of range: {height}") - return bytes.fromhex(OFFER_TREE_TYPE_HASHES[height]) - - def _bytes32(v): raw = bytes.fromhex(v.removeprefix("0x")) assert len(raw) == 32, f"expected 32 bytes, got {len(raw)}" @@ -241,46 +205,6 @@ def build_dense(leaves, claimed_root): } -# Reconstructs the EIP-712 digest for an OfferTree and either signs it locally -# (`signerKey`) or accepts a precomputed (signer, v, r, s). -def build_eip712(eip712_in, root, leaf_length): - ratifier = w3.to_checksum_address(eip712_in["ratifier"]) - chain_id = int(eip712_in["chainId"]) - height = (leaf_length - 1).bit_length() - if 1 << height != leaf_length: - raise ValueError( - f"eip712 requires a balanced tree; leafLength {leaf_length} is not a power of two" - ) - - struct_hash = _keccak_abi( - ["bytes32", "bytes32"], [offer_tree_typehash(height), _bytes32(root)] - ) - domain_separator = _keccak_abi( - ["bytes32", "uint256", "address"], [EIP712_DOMAIN_TYPEHASH, chain_id, ratifier] - ) - digest = w3.keccak(b"\x19\x01" + domain_separator + struct_hash) - - if "signerKey" in eip712_in: - signed = Account._sign_hash(digest, eip712_in["signerKey"]) - signer = Account.from_key(eip712_in["signerKey"]).address - v, r, s = signed.v, signed.r.to_bytes(32, "big"), signed.s.to_bytes(32, "big") - else: - signer = w3.to_checksum_address(eip712_in["signer"]) - v = int(eip712_in["v"]) - r = _bytes32(eip712_in["r"]) - s = _bytes32(eip712_in["s"]) - - return { - "ratifier": ratifier, - "chainId": chain_id, - "height": height, - "signer": signer, - "v": v, - "r": "0x" + r.hex(), - "s": "0x" + s.hex(), - } - - def main(): if len(sys.argv) != 2: print("usage: python create_certificate.py ", file=sys.stderr) @@ -292,9 +216,6 @@ def main(): root = proofs["root"] certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) - if "eip712" in proofs: - certificate["eip712"] = build_eip712(proofs["eip712"], root, certificate["treeLeafLength"]) - with open("certificate.json", "w") as f: json.dump(certificate, f, indent=2) From 7091ed9ba5cff426d2e6456bb3fd3157d51eafd1 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 1 Jun 2026 18:13:09 +0200 Subject: [PATCH 028/159] added justification rules for the hashLeaf trick --- certora/helpers/OfferTree.sol | 4 ++++ certora/specs/OfferTreeWellFormed.spec | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 939a89a73..115044ffa 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -114,6 +114,10 @@ contract OfferTree { return HashLib.hashOffer(offer); } + function hashNode(bytes32 left, bytes32 right) public pure returns (bytes32) { + return HashLib.hashNode(left, right); + } + function _hashLeaf(bytes32 id) public view returns (bytes32) { return _hashLeaf(tree[id].leaf); } diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 92c5cd575..3b62b908c 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,13 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// No hashing summaries are needed: `Node` stores only the fixed-size pre-image of `hashOffer` (see OfferTree.sol), -// so `isWellFormed` re-hashes a leaf with a single bounded keccak over fixed-size storage — no dynamic-array reads, -// no loops. The only dynamic hashing is `newLeaf` hashing its offer argument once, which is cheap. +// Leaves store the fixed-size pre-image of `hashOffer` (its scalar fields plus `marketHash` and `callbackDataHash`) +// instead of the raw `Offer`, so `isWellFormed` re-hashes a leaf with one bounded keccak (`_hashLeaf`) and the +// invariant scales. The rules below justify the trick: `newLeafConnectsHashLeafToHashOffer` checks `_hashLeaf` +// faithfully reproduces `hashOffer`, `leafHashDisjointFromNodeHash` checks leaf and internal hashes never collide, +// and `nodeHashInjective` underpins the merkle reasoning in OfferTreeMembership.spec. methods { function newLeaf(OfferTree.Offer) external envfree; function _hashLeaf(bytes32) external returns (bytes32) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; + function hashNode(bytes32, bytes32) external returns (bytes32) envfree; function isEmpty(bytes32) external returns (bool) envfree; function isWellFormed(bytes32) external returns (bool) envfree; } @@ -25,9 +28,7 @@ strong invariant wellFormed(bytes32 id) } } -// Focused bridge check: `newLeaf` keys the node by `HashLib.hashOffer(offer)` and stores the fixed-size -// pre-image that `_hashLeaf` re-hashes. This rule catches drift between `_hashLeaf` and the real offer hash -// construction. +// `_hashLeaf` reproduces the real `hashOffer` for the pre-image stored by `newLeaf`. rule newLeafConnectsHashLeafToHashOffer(OfferTree.Offer offer) { bytes32 id = hashOffer(offer); @@ -39,3 +40,14 @@ rule newLeafConnectsHashLeafToHashOffer(OfferTree.Offer offer) { assert _hashLeaf(id) == id; assert _hashLeaf(id) == hashOffer(offer); } + +// A recomputed leaf hash never equals an internal-node hash: image(_hashLeaf) and image(hashNode) are disjoint. +rule leafHashDisjointFromNodeHash(bytes32 id, bytes32 a, bytes32 b) { + assert _hashLeaf(id) != hashNode(a, b); +} + +// hashNode is injective, which the merkle peeling in OfferTreeMembership.spec relies on. +rule nodeHashInjective(bytes32 a, bytes32 b, bytes32 c, bytes32 d) { + require hashNode(a, b) == hashNode(c, d); + assert a == c && b == d; +} From 9d0635b90bf8b5ac2b38caccb7f8562c966135ef Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 16:55:55 +0200 Subject: [PATCH 029/159] removed assumptions from soundness rule --- certora/specs/OfferTreeMembership.spec | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index b8d1abcda..b5f3fb418 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -12,29 +12,18 @@ methods { function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; } -// The main correctness result of the verification. -// It ensures that if the root is setup according to a well-formed offer tree, then a successful Merkle verification of an offer against that root implies the offer is registered as a leaf in the tree. +// Headline Correctness Rule: +// If the root is setup according to a well-formed offer tree, then a successful Merkle verification of an offer against that root implies the offer is registered as a leaf in the tree. rule membershipSoundness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; - // Assume that root is the hash of node in the tree. - require OfferTree.getHash(node) == root; + require OfferTree.getHash(node) == root, "root is the hash of node"; - // Assume that the root is non-zero, otherwise empty nodes would hash-match it. - require root != to_bytes32(0); + require(OfferTree.wellFormedPath(node, leafIndex, proof), "the path from the root to the leaf is well-formed"); - // No need to make sure that node is equal to the root: one can pass an internal node instead. - // Assume that the tree is well-formed along the path down to the leaf. - OfferTree.wellFormedPath(node, leafIndex, proof); - - // Compute the leaf identifier once so both uses below bind to the same hash. bytes32 leafId = Utils.hashOffer(offer); - // Assume that the leaf identifier is non-zero, matching the constraint enforced by newLeaf. - require leafId != to_bytes32(0); - - // Assume that the Merkle proof verifies the offer's hash against the root. - require Utils.isLeaf(root, leafId, leafIndex, proof); + require Utils.isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; assert OfferTree.isLeafNode(leafId); } From 4a3f12168b02593e848dd7f5058ee699ae0a51cd Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 16:56:31 +0200 Subject: [PATCH 030/159] tuned --- certora/specs/OfferTreeMembership.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index b5f3fb418..7256cdc43 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -7,7 +7,6 @@ methods { function OfferTree.getHash(bytes32) external returns (bytes32) envfree; function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; - function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; } From 5dec1247d6d2fc3614e8f31947e010eccfde97d9 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 19:21:55 +0200 Subject: [PATCH 031/159] tuned; retained market-level hashLeaf --- certora/helpers/OfferTree.sol | 37 +++++++++++++------------- certora/specs/OfferTreeWellFormed.spec | 23 +++++++--------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 115044ffa..2b09a6a18 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -5,14 +5,14 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib, OFFER_TYPEHASH} from "../../src/ratifiers/libraries/HashLib.sol"; -// A leaf's offer reaches `HashLib.hashOffer` only through fixed-size fields: every dynamic member of `Offer` -// (`market.collateralParams` and `callbackData`) is already reduced to a single `bytes32` before the final -// keccak (`hashMarket(market)` and `keccak256(callbackData)`). So we store that fixed-size pre-image instead -// of the raw `Offer`. This keeps every `Node` fixed-size, so `isWellFormed` re-hashes a leaf with one bounded +// A leaf's offer reaches HashLib.hashOffer only through fixed-size fields: every dynamic member of Offer +// (market.collateralParams and callbackData) is already reduced to a single bytes32 before the final +// keccak (hashMarket(market) and keccak256(callbackData)). So we store that fixed-size pre-image instead +// of the raw Offer. This keeps every Node fixed-size, so isWellFormed re-hashes a leaf with one bounded // keccak (no dynamic-array reads, no loops) — the property that lets the wellFormed invariant scale, exactly -// as it does for URD's fixed-size leaves. `_hashLeaf` mirrors `hashOffer`'s outer keccak field-for-field, so a -// leaf's id is the real `hashOffer` value; the wellFormed invariant's `newLeaf` case checks this mirror holds -// (`id == hashOffer(offer)` and `id == _hashLeaf(leaf)`), so the correspondence is verified, not assumed. +// as it does for URD's fixed-size leaves. _hashLeaf mirrors hashOffer's outer keccak field-for-field, so a +// leaf's id is the real hashOffer value; the wellFormed invariant's newLeaf case checks this mirror holds +// (id == hashOffer(offer) and id == _hashLeaf(leaf)), so the correspondence is verified, not assumed. struct Leaf { bytes32 marketHash; // = HashLib.hashMarket(offer.market) bool buy; @@ -42,14 +42,13 @@ contract OfferTree { /* STORAGE */ // The tree has no root because every node (and the nodes underneath) form an offer tree. - // We use bytes32 as keys of the mapping so that leaves can have an identifier that is the hash of the offer. - // This ensures that the same offer does not appear twice as a leaf in the tree. + // We use bytes32 as keys of the mapping so that leaves have an identifier that is the hash of the offer. + // Identical offers therefore share a single node (referenced by multiple parents). // For internal nodes the key is left arbitrary, so that the certificate generation can choose freely any bytes32 // value (that is not already used). - // Leaves keep the fixed-size pre-image of `hashOffer` (see `Leaf`) so `isWellFormed` can recompute a leaf's hash - // and pin its `hashNode` into the image of `hashOffer`. Because `hashOffer` and `hashNode` feed keccak distinct - // input shapes, this gives domain separation between leaves and internal nodes for free under Certora's keccak - // model. The tree is built only via `newLeaf` and `newInternalNode`, which preserve well-formedness by + // Leaves keep the fixed-size pre-image of hashOffer (see Leaf) so isWellFormed can recompute a leaf's hash + // and pin its hashNode into the image of hashOffer. hashOffer and hashNode feed keccak distinct + // input shapes, this gives domain separation between leaves and internal nodes. The tree is built only via newLeaf and newInternalNode, which preserve well-formedness by // construction. mapping(bytes32 => Node) internal tree; @@ -60,7 +59,7 @@ contract OfferTree { require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; require(_isEmpty(n), "leaf is not empty"); - // Store the fixed-size pre-image of `hashOffer`; the dynamic members are kept only as their sub-hashes. + // Store the fixed-size pre-image of hashOffer; the dynamic members are kept only as their sub-hashes. Leaf storage l = n.leaf; l.marketHash = HashLib.hashMarket(offer.market); l.buy = offer.buy; @@ -122,9 +121,9 @@ contract OfferTree { return _hashLeaf(tree[id].leaf); } - // Recompute the leaf hash from its stored fixed-size pre-image. Mirrors `HashLib.hashOffer`'s outer keccak - // field-for-field, with `marketHash` standing in for `hashMarket(market)` and `callbackDataHash` for - // `keccak256(callbackData)`. Equals `HashLib.hashOffer(offer)` whenever the fields were extracted from `offer`. + // Recompute the leaf hash from its stored fixed-size pre-image. Mirrors HashLib.hashOffer's outer keccak + // field-for-field, with marketHash standing in for hashMarket(market) and callbackDataHash for + // keccak256(callbackData). Equals HashLib.hashOffer(offer) whenever the fields were extracted from offer. function _hashLeaf(Leaf storage l) internal view returns (bytes32) { return keccak256( abi.encode( @@ -167,8 +166,8 @@ contract OfferTree { return false; } - // Check that the nodes are well-formed starting from `id` and going down the `tree`. - // The bits of `leafIndex` choose the path downward; the depth is `proof.length`. + // Check that the nodes are well-formed starting from id and going down the tree. + // The bits of leafIndex choose the path downward; the depth is proof.length. function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bool) { for (uint256 i = proof.length;;) { require(isWellFormed(id)); diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 3b62b908c..0c87937e0 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// Leaves store the fixed-size pre-image of `hashOffer` (its scalar fields plus `marketHash` and `callbackDataHash`) -// instead of the raw `Offer`, so `isWellFormed` re-hashes a leaf with one bounded keccak (`_hashLeaf`) and the -// invariant scales. The rules below justify the trick: `newLeafConnectsHashLeafToHashOffer` checks `_hashLeaf` -// faithfully reproduces `hashOffer`, `leafHashDisjointFromNodeHash` checks leaf and internal hashes never collide, -// and `nodeHashInjective` underpins the merkle reasoning in OfferTreeMembership.spec. +// Leaves store the fixed-size pre-image of hashOffer (its static fields plus marketHash and callbackDataHash) +// instead of the raw Offer, so isWellFormed re-hashes a leaf with one bounded keccak (_hashLeaf) and the +// wellFormed proof stays bounded regardless of offer size (no dynamic-array loops, no dynamic-length hashing). +// hashLeafReproducesHashOffer justifies the trick: the stored pre-image re-hashes +// to the real hashOffer. leafHashDisjointFromNodeHash and nodeHashInjective record the two keccak-model +// properties (leaf/internal domain separation, hashNode injectivity) that OfferTreeMembership.spec relies on. methods { function newLeaf(OfferTree.Offer) external envfree; @@ -28,17 +29,13 @@ strong invariant wellFormed(bytes32 id) } } -// `_hashLeaf` reproduces the real `hashOffer` for the pre-image stored by `newLeaf`. -rule newLeafConnectsHashLeafToHashOffer(OfferTree.Offer offer) { - bytes32 id = hashOffer(offer); - - require id != to_bytes32(0); - require isEmpty(id); - +// _hashLeaf reproduces the real hashOffer for the leaf stored by newLeaf. +// newLeaf is called without @withrevert, so its own guards (id != 0, slot empty) hold as assumptions. +rule hashLeafReproducesHashOffer(OfferTree.Offer offer) { newLeaf(offer); + bytes32 id = hashOffer(offer); assert _hashLeaf(id) == id; - assert _hashLeaf(id) == hashOffer(offer); } // A recomputed leaf hash never equals an internal-node hash: image(_hashLeaf) and image(hashNode) are disjoint. From 956a11f9c60e2b100e3218c3d8fa616a7e6148aa Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 20:42:48 +0200 Subject: [PATCH 032/159] cleanup ratification spec --- certora/specs/Ratification.spec | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index fe3e27fa4..ecc3499ec 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -7,7 +7,6 @@ methods { function isAuthorized(address authorizer, address authorized) external returns (bool) envfree; - function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; function Utils.callbackSuccess() external returns (bytes32) envfree; function _.isRatified(Midnight.Offer, bytes) external => DISPATCHER(true); @@ -17,7 +16,7 @@ methods { function _.transfer(address, uint256) external => NONDET; // Capture HashLib.isLeaf's return; needed by `isRatifiedRequiresIsLeaf` to assert isRatified gates on a merkle check. - function HashLib.isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) internal returns (bool) => isLeafCapture(root, leafHash, leafIndex, proof); + function HashLib.isLeaf(bytes32, bytes32, uint256, bytes32[] memory) internal returns (bool) => isLeafCapture(); function HashLib.hashOffer(Midnight.Offer memory) internal returns (bytes32) => NONDET; function HashLib.offerTreeTypeHash(uint256) internal returns (bytes32) => NONDET; @@ -33,15 +32,11 @@ methods { function tradingFee(bytes32, uint256) internal returns (uint256) => NONDET; } -function summaryHashOffer(Midnight.Offer offer) returns bytes32 { - return Utils.hashOffer(offer); -} - // Captures whether HashLib.isLeaf was called and returned true during the current rule. // Used by `isRatifiedRequiresIsLeaf` to assert that every successful isRatified gates on a merkle check. persistent ghost bool isLeafReturnedTrue; -function isLeafCapture(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] proof) returns bool { +function isLeafCapture() returns bool { bool ret; if (ret) { isLeafReturnedTrue = true; From ea946969253c9fe0694f0e36e73796c9a2867555 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 20:44:42 +0200 Subject: [PATCH 033/159] varibale renaming in create_certificate.py; tuned checker --- certora/checker/Checker.sol | 39 ++++++++++++--------------- certora/checker/create_certificate.py | 12 ++++----- certora/helpers/Utils.sol | 11 +++----- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol index 1a5e4445f..540308c9f 100644 --- a/certora/checker/Checker.sol +++ b/certora/checker/Checker.sol @@ -20,27 +20,6 @@ contract Checker is Test { // Replay the certificate through the verified `newLeaf` and `newInternalNode` // primitives, then assert that the final certificate item matches `root`. - function _verifyCertificate(Offer[] memory leaves, InternalNode[] memory nodes, bytes32 root) internal { - require(leaves.length > 0, "no leaves"); - require(nodes.length > 0 || leaves.length == 1, "missing internal nodes"); - - OfferTree tree = new OfferTree(); - - for (uint256 i = 0; i < leaves.length; i++) { - tree.newLeaf(leaves[i]); - } - - bytes32 rootId = HashLib.hashOffer(leaves[0]); - for (uint256 i = 0; i < nodes.length; i++) { - InternalNode memory node = nodes[i]; - tree.newInternalNode(node.id, node.left, node.right); - rootId = node.id; - } - - assertTrue(!tree.isEmpty(rootId), "empty root"); - assertEq(tree.getHash(rootId), root, "mismatched roots"); - } - function testVerifyCertificate() public { string memory path = string.concat(vm.projectRoot(), "/certificate.json"); if (!vm.exists(path)) vm.skip(true, "no certificate.json at project root"); @@ -62,6 +41,22 @@ contract Checker is Test { nodes[i] = abi.decode(enc, (InternalNode)); } - _verifyCertificate(leaves, nodes, root); + require(leaves.length > 0, "no leaves"); + require(nodes.length > 0 || leaves.length == 1, "missing internal nodes"); + + OfferTree tree = new OfferTree(); + + for (uint256 i = 0; i < leaves.length; i++) { + tree.newLeaf(leaves[i]); + } + + bytes32 rootId = HashLib.hashOffer(leaves[0]); + for (uint256 i = 0; i < nodes.length; i++) { + InternalNode memory node = nodes[i]; + tree.newInternalNode(node.id, node.left, node.right); + rootId = node.id; + } + + assertEq(tree.getHash(rootId), root, "mismatched roots"); } } diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index 34a99eb30..566b37b33 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -162,10 +162,11 @@ def hash_node(left, right): return w3.to_hex(w3.keccak(_bytes32(left) + _bytes32(right))) -# Builds a dense certificate from a power-of-two list of offers, in leftIndex order. -def build_dense(leaves, claimed_root): +# Builds a certificate from a power-of-two list of offers, in leftIndex order, by pairing +# leaves level-by-level into a perfect binary tree. +def build_certificate(leaves, claimed_root): n = len(leaves) - assert n > 0 and (n & (n - 1)) == 0, "dense leaves count must be a power of two" + assert n > 0 and (n & (n - 1)) == 0, "leaves count must be a power of two" leaf_instructions = {} node_instructions = {} @@ -192,12 +193,11 @@ def build_dense(leaves, claimed_root): level = next_level assert level[0].lower() == claimed_root.lower(), ( - f"dense: computed root {level[0]} != claimed root {claimed_root}" + f"computed root {level[0]} != claimed root {claimed_root}" ) return { "root": claimed_root, - "treeLeafLength": n, "leafLength": len(leaf_instructions), "leaf": list(leaf_instructions.values()), "nodeLength": len(node_instructions), @@ -214,7 +214,7 @@ def main(): proofs = json.load(f) root = proofs["root"] - certificate = build_dense([entry["offer"] for entry in proofs["leaves"]], root) + certificate = build_certificate([entry["offer"] for entry in proofs["leaves"]], root) with open("certificate.json", "w") as f: json.dump(certificate, f, indent=2) diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index fa557338d..aa1ff6552 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -19,18 +19,13 @@ contract Utils { } // Wraps `HashLib.hashOffer` directly so CVL specs can expose the real EIP-712 offer hash - // envfree. Avoids the prior `keccak256(abi.encode(offer))` reimplementation, which is a - // *different* hash than `HashLib.hashOffer` (no typehash prefix, no inner hashing of - // market/callbackData) and broke keccak unification across summary boundaries when the - // prover had to forward-compute the merkle chain (completeness direction). + // envfree. Used by OfferTreeMembership.spec as the leaf id. A `keccak256(abi.encode(offer))` + // reimplementation would be a *different* hash (no typehash prefix, no inner hashing of + // market/callbackData), so we forward to the real library function. function hashOffer(Offer memory offer) external pure returns (bytes32) { return HashLib.hashOffer(offer); } - function hashNode(bytes32 a, bytes32 b) external pure returns (bytes32) { - return HashLib.hashNode(a, b); - } - function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) external pure From fa88df5df8c60be82c680f46a73d30f832798e15 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 21:24:23 +0200 Subject: [PATCH 034/159] added high-level verification approach in README --- certora/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/certora/README.md b/certora/README.md index 62199d767..007980423 100644 --- a/certora/README.md +++ b/certora/README.md @@ -43,6 +43,37 @@ How offers are consumed when taken. - [`EmptyOffer.spec`](specs/EmptyOffer.spec) checks that taking an empty offer always reverts (so the offer tree can be padded with empty offers). - [`Ratification.spec`](specs/Ratification.spec) checks that every successful take requires the maker to have authorized the ratifier. +## Offer trees + +Offers are authorized in batches: a ratifier signs a single Merkle root over an offer tree, and a `take` only succeeds if the offer's hash is proven to be a leaf under that root. +Objective is to show that a successful `take` can only settle an offer that was genuinely committed in the signed tree. +We reason about [`OfferTree`](helpers/OfferTree.sol), a model of the tree built only through the `newLeaf` and `newInternalNode` primitives. Leaves are keyed by `HashLib.hashOffer(offer)` and store a fixed-size pre-image of the offer, so `isWellFormed` re-hashes a leaf with a single bounded keccak instead of looping over the offer's dynamic members, which keeps the proofs bounded regardless of offer size. + +- [`OfferTreeWellFormed.spec`](specs/OfferTreeWellFormed.spec) checks that the primitives only ever build well-formed trees: every node is empty, a leaf carrying a genuine `hashOffer`, or an internal node correctly hashing its two children. +- [`OfferTreeMembership.spec`](specs/OfferTreeMembership.spec) checks the main soundness result: for any well-formed tree, if a Merkle proof verifies an offer's hash against the root, then the offer is registered as a leaf. Equivalently, no valid proof can be forged for an offer that is not in the tree. +- [`Ratification.spec`](specs/Ratification.spec) connects this to the on-chain path: every successful `isRatified` (across all ratifier implementations) and every successful `take` actually invokes `HashLib.isLeaf` and it returns true. + +Combining the three: a successful `take` runs a Merkle membership check against the ratified root (`Ratification`), which for a well-formed root implies the offer is genuinely a leaf of that tree (`OfferTreeMembership`), and the root is well-formed because it is built only from the well-formedness-preserving primitives (`OfferTreeWellFormed`). + +### Checking a concrete root + +The membership result is stated for any well-formed root; the checker in [`checker`](checker) lets anyone confirm what a specific root commits to, by rebuilding the tree through the same verified primitives. + +1. Write a `proofs.json` listing the claimed `root` and the offers (`leaves`), padded to a power of two with empty offers. +2. Generate the certificate, from the repository root: + ``` + python certora/checker/create_certificate.py proofs.json + ``` + This recomputes the tree bottom-up, asserts the computed root equals the claimed `root`, and writes `certificate.json`. +3. Replay it through the verified primitives: + ``` + FOUNDRY_PROFILE=checker forge test --match-test testVerifyCertificate + ``` + [`Checker.sol`](checker/Checker.sol) reads `certificate.json`, rebuilds the tree via `OfferTree.newLeaf`/`newInternalNode`, and asserts the constructed root equals `root`. + +A passing run certifies that the root is the root of a well-formed tree built from exactly those offers, so the membership guarantee applies to it. +This confirms what a root commits to, not that it was signed; verifying the ratifier's signature is a separate step. + ## Fees Continuous-fee accrual and settlement-fee rounding stay within their expected bounds. From a1b4b8ecabf4e126d40b2e295a800c659cc61b08 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 21:27:33 +0200 Subject: [PATCH 035/159] fmt --- certora/helpers/OfferTree.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 2b09a6a18..f25185128 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -48,8 +48,8 @@ contract OfferTree { // value (that is not already used). // Leaves keep the fixed-size pre-image of hashOffer (see Leaf) so isWellFormed can recompute a leaf's hash // and pin its hashNode into the image of hashOffer. hashOffer and hashNode feed keccak distinct - // input shapes, this gives domain separation between leaves and internal nodes. The tree is built only via newLeaf and newInternalNode, which preserve well-formedness by - // construction. + // input shapes, this gives domain separation between leaves and internal nodes. The tree is built only via newLeaf + // and newInternalNode, which preserve well-formedness by construction. mapping(bytes32 => Node) internal tree; /* MAIN FUNCTIONS */ From be2a5635c1f47a5944d16bfed63e9e74943f9626 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 21:45:22 +0200 Subject: [PATCH 036/159] acknowledge URD spec in README --- certora/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/certora/README.md b/certora/README.md index 007980423..01e2d01c6 100644 --- a/certora/README.md +++ b/certora/README.md @@ -74,6 +74,8 @@ The membership result is stated for any well-formed root; the checker in [`check A passing run certifies that the root is the root of a well-formed tree built from exactly those offers, so the membership guarantee applies to it. This confirms what a root commits to, not that it was signed; verifying the ratifier's signature is a separate step. +The verification setup and technique is inspired from the Merkle Tree Membership soundness spec in [Universal Rewards Distributor](https://github.com/morpho-org/universal-rewards-distributor/). + ## Fees Continuous-fee accrual and settlement-fee rounding stay within their expected bounds. From 6aaa42049a8aa36b1c852ddc894323b25a788ae9 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 2 Jun 2026 21:59:58 +0200 Subject: [PATCH 037/159] asserts replaced with raising exceptions --- certora/checker/create_certificate.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index 566b37b33..3b281a805 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -26,9 +26,15 @@ INTERNAL_NODE_ABI_TYPE = "(bytes32,bytes32,bytes32)" +# Safety checks use this instead of `assert`, which is stripped under `python -O`. +def _require(cond, msg): + if not cond: + raise ValueError(msg) + + def _bytes32(v): raw = bytes.fromhex(v.removeprefix("0x")) - assert len(raw) == 32, f"expected 32 bytes, got {len(raw)}" + _require(len(raw) == 32, f"expected 32 bytes, got {len(raw)}") return raw @@ -166,7 +172,7 @@ def hash_node(left, right): # leaves level-by-level into a perfect binary tree. def build_certificate(leaves, claimed_root): n = len(leaves) - assert n > 0 and (n & (n - 1)) == 0, "leaves count must be a power of two" + _require(n > 0 and (n & (n - 1)) == 0, "leaves count must be a power of two") leaf_instructions = {} node_instructions = {} @@ -175,7 +181,7 @@ def build_certificate(leaves, claimed_root): for leaf, leaf_hash in zip(leaves, level): encoded_leaf = abi_encode_offer(leaf) previous = leaf_instructions.setdefault(leaf_hash, encoded_leaf) - assert previous == encoded_leaf, "leaf hash collides with a different offer" + _require(previous == encoded_leaf, "leaf hash collides with a different offer") while len(level) > 1: next_level = [] @@ -183,17 +189,16 @@ def build_certificate(leaves, claimed_root): left = level[2 * i] right = level[2 * i + 1] node_hash = hash_node(left, right) - assert ( - node_hash not in leaf_instructions - ), "internal node id collides with a leaf id" + _require(node_hash not in leaf_instructions, "internal node id collides with a leaf id") encoded_node = abi_encode_node(node_hash, left, right) previous = node_instructions.setdefault(node_hash, encoded_node) - assert previous == encoded_node, "internal node id collides with different children" + _require(previous == encoded_node, "internal node id collides with different children") next_level.append(node_hash) level = next_level - assert level[0].lower() == claimed_root.lower(), ( - f"computed root {level[0]} != claimed root {claimed_root}" + _require( + level[0].lower() == claimed_root.lower(), + f"computed root {level[0]} != claimed root {claimed_root}", ) return { From bec4e8f256f249a37e50f55c9547af34d484805d Mon Sep 17 00:00:00 2001 From: Bhargav Date: Wed, 3 Jun 2026 08:54:46 +0200 Subject: [PATCH 038/159] tuned --- certora/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certora/README.md b/certora/README.md index 01e2d01c6..b2da4a4f0 100644 --- a/certora/README.md +++ b/certora/README.md @@ -49,7 +49,7 @@ Offers are authorized in batches: a ratifier signs a single Merkle root over an Objective is to show that a successful `take` can only settle an offer that was genuinely committed in the signed tree. We reason about [`OfferTree`](helpers/OfferTree.sol), a model of the tree built only through the `newLeaf` and `newInternalNode` primitives. Leaves are keyed by `HashLib.hashOffer(offer)` and store a fixed-size pre-image of the offer, so `isWellFormed` re-hashes a leaf with a single bounded keccak instead of looping over the offer's dynamic members, which keeps the proofs bounded regardless of offer size. -- [`OfferTreeWellFormed.spec`](specs/OfferTreeWellFormed.spec) checks that the primitives only ever build well-formed trees: every node is empty, a leaf carrying a genuine `hashOffer`, or an internal node correctly hashing its two children. +- [`OfferTreeWellFormed.spec`](specs/OfferTreeWellFormed.spec) checks that the primitives only ever build well-formed trees: every node is empty, a leaf carrying a genuine `hashOffer`, or an internal node correctly hashing its two children. In particular, there is no restriction for the left and right children of a parent node to be sorted. - [`OfferTreeMembership.spec`](specs/OfferTreeMembership.spec) checks the main soundness result: for any well-formed tree, if a Merkle proof verifies an offer's hash against the root, then the offer is registered as a leaf. Equivalently, no valid proof can be forged for an offer that is not in the tree. - [`Ratification.spec`](specs/Ratification.spec) connects this to the on-chain path: every successful `isRatified` (across all ratifier implementations) and every successful `take` actually invokes `HashLib.isLeaf` and it returns true. From 6a5f89738b91ed311ed4a3ef63a5acdd26f001f6 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Sun, 9 Aug 2026 15:52:31 +0200 Subject: [PATCH 039/159] updated to match latest midnight --- certora/checker/OfferVerificationToolChain.md | 229 ++++++++++++++++++ certora/checker/create_certificate.py | 59 ++++- certora/confs/OfferTreeMembership.conf | 1 + certora/confs/OfferTreeWellFormed.conf | 1 + certora/helpers/OfferTree.sol | 5 +- 5 files changed, 285 insertions(+), 10 deletions(-) create mode 100644 certora/checker/OfferVerificationToolChain.md diff --git a/certora/checker/OfferVerificationToolChain.md b/certora/checker/OfferVerificationToolChain.md new file mode 100644 index 000000000..dd60d474c --- /dev/null +++ b/certora/checker/OfferVerificationToolChain.md @@ -0,0 +1,229 @@ +# The Offer Verification Toolchain + +How a maker can know — without trusting the front end, the SDK, their wallet software, or +their hardware wallet's EIP-712 parser — that the offer-tree root they approve commits to +exactly the offers they intend, and nothing else. + +## Why this exists: hardware wallets cannot clear-sign the tree + +Makers originally clear-signed the full EIP-712 `OfferTree`. Its Merkle representation is +a deeply nested array type (`Offer[2][2]…[2]`), and hardware-wallet firmware must parse +that structure on-device to clear-sign it. Much of the ecosystem cannot: + +- **Ledger** (Nano X / S Plus / Flex / Stax): the clear-sign path fails with `0x6a00` on + larger nested trees; older Ethereum apps (1.17–1.19.3) could produce an *incorrect + signature* due to a device-side hashing bug. +- **Trezor** (Model T / Safe 3/5/7): hard failure — firmware does not support + arrays-of-arrays. +- **Original Nano S**: blind signing works but displays nothing meaningful. +- **Custody platforms**: same failure class at different limits (a 64-leaf + `Offer[2][2][2][2][2][2]` exceeded one vendor's nesting cap of 10). +- **Software wallets** work only because the *host* computes the digest — which is + exactly the machine we don't want to have to trust. + +The failure is structural, not fixable by simplifying an offer field: a routine +single-market chain reaches 32 leaves (six array levels), and multi-market trees reach +256 leaves. Behavior also depends on wallet *software*, not just the device (the same +Ledger succeeded through one wallet's blind-sign path and failed through another's +clear-sign path), and a dapp can neither choose that path nor detect that an EIP-1193 +account is hardware-backed. + +**The decision shipped:** makers approve the tree *root* instead of signing the tree — +today via an on-chain [`SetterRatifier`](../../src/ratifiers/SetterRatifier.sol) +transaction (hardware-compatible, reversible, one cheap transaction per batch); longer +term via a root-only EIP-712 ratifier that restores off-chain signing without exposing +the nested type to device parsers. + +This fixes the device problem but creates a verification problem: **the root is an opaque +32 bytes**. The device can display it faithfully, but nothing on the device tells the +maker what it commits them to. The toolchain in this directory rebuilds that missing +"what am I approving?" verification as an independent, locally runnable pipeline. + +## The trust chain + +``` +offers JSON (human-reviewed intent) + │ create_certificate.py — independent Python implementation (eth_abi/web3) + ▼ +root + certificate.json (flat leaf/node instruction lists — no nested arrays anywhere) + │ Checker.sol — replays through the real HashLib via OfferTree.newLeaf/newInternalNode + ▼ +"the root matches under Solidity's own hashing" + │ Certora proofs — OfferTreeWellFormed.spec + OfferTreeMembership.spec + ▼ +"the root commits to EXACTLY these offers at settlement time" + │ device screen — compare 32 bytes + ▼ +root approval (SetterRatifier tx today; root-only EIP-712 signature later) +``` + +Each link removes one party from the trusted base. No single tool is trusted: the Python +and Solidity implementations share no code and must agree, and the formal proofs pin down +what their agreement *means*. + +## The maker's workflow, step by step + +### Step 0 — Formal verification of the primitives (per release, not per user) + +Run by CI: `certoraRun certora/confs/OfferTreeWellFormed.conf` and +`certora/confs/OfferTreeMembership.conf`. + +- [`OfferTreeWellFormed.spec`](../specs/OfferTreeWellFormed.spec) proves that any tree + built through `newLeaf`/`newInternalNode` is well-formed, that a stored leaf re-hashes + to the real `HashLib.hashOffer` (`hashLeafReproducesHashOffer`), and states the two + keccak-model axioms the whole chain rests on: leaf/internal-node domain separation + (`leafHashDisjointFromNodeHash`) and `hashNode` injectivity. +- [`OfferTreeMembership.spec`](../specs/OfferTreeMembership.spec) proves the headline + (`membershipSoundness`): an offer that passes on-chain `HashLib.isLeaf` against a + well-formed root **is a leaf of that tree**. + +**Guarantee:** a root is a binding commitment to exactly its leaf set — no hidden leaf, +no internal-node-as-leaf forgery, no offer with tweaked fields. +**Still open:** whether *your* root was computed from *your* offers. + +### Step 1 — Read the offers + +The front end / SDK produces `proofs.json`: the claimed root plus every offer in plain +fields (market, tick, expiry, `maxUnits`, `maxAssets`, `reduceOnly`, …). + +**Guarantee:** none — this is the intent step. Everything downstream proves the root +commits to *this file*, so this is the only thing the maker must actually read. + +### Step 2 — Independent root recomputation + +``` +python certora/checker/create_certificate.py proofs.json +``` + +Recomputes every hash bottom-up with an implementation +([`create_certificate.py`](create_certificate.py), built on `eth_abi`/`web3`) that shares +no code with the front end, and writes `certificate.json`. It hard-fails on root +mismatch, on leaf/node hash collisions, and — via `_check_typehashes`, which re-derives +the three EIP-712 typehashes from their type strings (mirroring +[`HashLibTest.sol`](../../test/HashLibTest.sol)) — on any typehash drift after a struct +change. + +**Guarantee:** the claimed root derives from the reviewed offers, independently of the +dapp, the SDK, wallet middleware, and device firmware. This removes exactly the failure +modes observed in the field: a divergent wallet signing path, a device hashing bug, a +tampered front end. +**Still open:** the Python mirror itself could mis-implement Solidity's hashing. + +### Step 3 — Canonical replay through Solidity + +``` +FOUNDRY_PROFILE=checker forge test --match-test testVerifyCertificate +``` + +[`Checker.sol`](Checker.sol) reads `certificate.json`, rebuilds the tree through +[`OfferTree.newLeaf`/`newInternalNode`](../helpers/OfferTree.sol) — which hash with the +**actual** [`HashLib`](../../src/ratifiers/libraries/HashLib.sol) Midnight executes at +settlement — and asserts the constructed root equals the claimed root. + +**Guarantee:** Python and Solidity cross-check each other, and one of them is the +canonical implementation. A bug in either makes the test fail; they cannot "agree +wrongly" unless two independent implementations share the same bug. +**Still open:** whether "these primitives reproduce the root" implies "the root commits +to exactly these offers" — which is precisely what Step 0 proved, over the very +primitives this replay uses. + +### Step 4 — Approve on the device + +Submit the root approval and compare the 32-byte root on the device screen against the +root printed in steps 2–3. + +- **Today:** `SetterRatifier.setIsRootRatified(maker, root, true)` — an ordinary + transaction, clear-signable on every device including Trezor and the original Nano S, + and *reversible* (set it back to `false` to unratify the whole batch). +- **Later:** a root-only EIP-712 signature — a flat struct with a single `bytes32`, no + nesting for any firmware to choke on. + +**Guarantee:** what the device displays is byte-for-byte the value the toolchain +verified. The device's inability to parse the tree no longer matters, because the tree +never reaches it. + +### Step 5 — Settlement + +Takers consume offers by presenting `(offer, leafIndex, proof)`; +[`SetterRatifier.isRatified`](../../src/ratifiers/SetterRatifier.sol) checks +`HashLib.isLeaf` against the approved root. + +**Guarantee (Step 0 + Steps 2–4 composed):** *the only offers that can ever settle under +this approval are exactly the ones in the file read in Step 1.* + +## The composed guarantee + +> If the 32 bytes on my device screen equal the root my local toolchain computed from +> offers I read, then my approval binds me to precisely those offers — nothing else. + +The front end, the SDK, the wallet software, and the device's EIP-712 parser are all +outside the trusted base. What remains: + +1. **The maker's own machine and toolchain** (Python deps, foundry, solc) — mitigable by + pinning/vendoring and running air-gapped. +2. **Keccak collision resistance** — stated explicitly as the `nodeHashInjective` / + `leafHashDisjointFromNodeHash` rules rather than assumed silently. +3. **Deployed bytecode = verified source** — the Certora proofs are about source; check + the deployed Midnight and ratifier addresses against it once (Etherscan/Sourcify). +4. **Semantic review** — the pipeline proves hash integrity, not that a tick or expiry is + sensible. Reading `proofs.json` in Step 1 is the one judgment step left in the flow. + +## Verifying a signature after the fact (EcrecoverRatifier path) + +For makers who *can* sign — note that +[`EcrecoverRatifier`](../../src/ratifiers/EcrecoverRatifier.sol) verifies a digest built +from the root alone: + +``` +structHash = keccak256(abi.encode(offerTreeTypeHash(height), root)) +domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)) +digest = keccak256("\x19\x01" ‖ domainSeparator ‖ structHash) +``` + +The nested `Offer[2][2]…` type exists only wallet-side: EIP-712's array hashing +(keccak of concatenated element hash-structs) recursively collapses to the Merkle root, +which is why `HashLib.hashNode` is exactly `keccak256(left ‖ right)`. + +A wallet never outputs a root, only `(v, r, s)` — so the after-the-fact check compares +*signers* instead of roots: recompute the root from the maker's own offers (steps 2–3), +rebuild the digest above from that recomputed root, and check +`ecrecover(digest, v, r, s)` equals the maker's address. A signature is valid for one +`(key, digest)` pair, and the digest is a collision-resistant function of the root — so +recovery yielding the maker's address is the cryptographic equivalent of "the signed root +equals the recomputed root". A front end that swapped offers changes the root, hence the +digest, and recovery yields some other address — never the maker's. (This check is not +currently implemented in `create_certificate.py`; the recipe above is what an +implementation must compute.) + +## If devices could clear-sign the tree, would this be redundant? + +Mostly — and seeing why sharpens what each piece is for. Correct clear signing fuses the +pipeline into one tamper-proof path: the trusted display is Step 1 (the digest is derived +on-device from the same bytes displayed, so host malware cannot decouple "what I read" +from "what gets hashed"), the device's firmware hashing is Step 2 (an independent +implementation isolated from the host), and EIP-712 conformance replaces Step 3 (device +and contract implement the same public standard, and `ecrecover` at settlement only +matches the maker if they agreed). There is no opaque root to compare, so Step 4's ritual +disappears too. + +Three things stay load-bearing regardless of signing method: + +1. **The contract-side proofs (Step 0).** `membershipSoundness` and domain separation + protect *settlement* against forged proofs — a taker re-presenting an internal 2-word + node hash as an "offer" — which has nothing to do with how the signature was made. +2. **Firmware as a single point of failure.** The Ledger 1.17–1.19.3 hashing bug is + exactly the failure this pipeline's two-independent-implementations design catches and + a device-only trust chain doesn't. The checker retains value as an audit layer. +3. **Review at scale.** Clear-signing 256 leaves × 15 fields on a device screen is + theoretical transparency but practical blind-signing-by-fatigue. A host-side JSON you + can read, diff, and script against is a better review surface for large trees. + +## Running it + +See the "checker" section of [`../README.md`](../README.md) for the two commands +(`create_certificate.py`, then `FOUNDRY_PROFILE=checker forge test`). + +## Internal references + +- Ledger investigation: MKT-1179 · SetterRatifier decision: MKT-1239 · custody nesting + cap: MKT-1552 (Linear, internal). diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py index 3b281a805..c3bdf5b98 100644 --- a/certora/checker/create_certificate.py +++ b/certora/checker/create_certificate.py @@ -6,21 +6,27 @@ w3 = Web3() +# Constants from src/ratifiers/libraries/HashLib.sol (checked against the type +# strings in test/HashLibTest.sol by _check_typehashes below). +COLLATERAL_PARAMS_TYPE = b"CollateralParams(address token,uint256 lltv,uint256 liquidationCursor,address oracle)" +MARKET_TYPE = b"Market(uint256 chainId,address midnight,address loanToken,CollateralParams[] collateralParams,uint256 maturity,uint256 rcfThreshold,address enterGate,address liquidatorGate)" +OFFER_TYPE = b"Offer(Market market,bool buy,address maker,uint256 start,uint256 expiry,uint256 tick,bytes32 group,address callback,bytes callbackData,address receiverIfMakerIsSeller,address ratifier,bool reduceOnly,uint128 maxUnits,uint128 maxAssets,uint256 continuousFeeCap)" + COLLATERAL_PARAMS_TYPEHASH = bytes.fromhex( - "af44a88eb50ebdbbebd980e5a23045c44f61ece5f80ab708a1bbe8718102e6af" + "39ed3f928d24fd00574b1a02aba9c2483abcf5d9a3a366118c9a5aa29885b841" ) MARKET_TYPEHASH = bytes.fromhex( - "358117e98511cc3df97175dca58053b06675b43ad090b0553f8a1eff008b6e2e" + "510b3862f3816a109c9340b76972e8a30984246be06e034ae12ed2934220391a" ) OFFER_TYPEHASH = bytes.fromhex( - "980a4cfc9766df84667f316d76e10cefc8caf04fb4cd4a9fca00a8e7b34f619c" + "9905214264a9fb7b6cc1b0e33db7a04687c6e4185a84755d29914314aa9d8906" ) # ABI signature for `Offer` matching src/interfaces/IMidnight.sol field order. OFFER_ABI_TYPE = ( "(" - "(address,(address,uint256,uint256,address)[],uint256,uint256,address,address)," - "bool,address,uint256,uint256,uint256,bytes32,address,bytes,address,address,bool,uint256,uint256" + "(uint256,address,address,(address,uint256,uint256,address)[],uint256,uint256,address,address)," + "bool,address,uint256,uint256,uint256,bytes32,address,bytes,address,address,bool,uint128,uint128,uint256" ")" ) INTERNAL_NODE_ABI_TYPE = "(bytes32,bytes32,bytes32)" @@ -46,16 +52,34 @@ def _keccak_abi(types, values): return w3.keccak(encode(types, values)) +# Pin the hardcoded typehashes to the EIP-712 type strings (mirrors test/HashLibTest.sol). +def _check_typehashes(): + _require( + w3.keccak(COLLATERAL_PARAMS_TYPE) == COLLATERAL_PARAMS_TYPEHASH, + "COLLATERAL_PARAMS_TYPEHASH does not match its type string", + ) + _require( + w3.keccak(MARKET_TYPE + COLLATERAL_PARAMS_TYPE) == MARKET_TYPEHASH, + "MARKET_TYPEHASH does not match its type string", + ) + _require( + w3.keccak(OFFER_TYPE + COLLATERAL_PARAMS_TYPE + MARKET_TYPE) == OFFER_TYPEHASH, + "OFFER_TYPEHASH does not match its type string", + ) + + # Returns the abi-encoded form of an Offer, ready for `abi.decode(bytes, (Offer))`. def abi_encode_offer(o): m = o["market"] market = ( + int(m["chainId"]), + w3.to_checksum_address(m["midnight"]), w3.to_checksum_address(m["loanToken"]), [ ( w3.to_checksum_address(cp["token"]), int(cp["lltv"]), - int(cp["maxLif"]), + int(cp["liquidationCursor"]), w3.to_checksum_address(cp["oracle"]), ) for cp in m["collateralParams"] @@ -80,6 +104,7 @@ def abi_encode_offer(o): bool(o["reduceOnly"]), int(o["maxUnits"]), int(o["maxAssets"]), + int(o["continuousFeeCap"]), ) return "0x" + encode([OFFER_ABI_TYPE], [offer]).hex() @@ -96,7 +121,7 @@ def hash_collateral_params(cp): COLLATERAL_PARAMS_TYPEHASH, w3.to_checksum_address(cp["token"]), int(cp["lltv"]), - int(cp["maxLif"]), + int(cp["liquidationCursor"]), w3.to_checksum_address(cp["oracle"]), ], ) @@ -108,9 +133,21 @@ def hash_market(m): ) collateral_params_hash = w3.keccak(collateral_params_hashes) return _keccak_abi( - ["bytes32", "address", "bytes32", "uint256", "uint256", "address", "address"], + [ + "bytes32", + "uint256", + "address", + "address", + "bytes32", + "uint256", + "uint256", + "address", + "address", + ], [ MARKET_TYPEHASH, + int(m["chainId"]), + w3.to_checksum_address(m["midnight"]), w3.to_checksum_address(m["loanToken"]), collateral_params_hash, int(m["maturity"]), @@ -139,7 +176,8 @@ def hash_offer(o): "address", "address", "bool", - "uint256", + "uint128", + "uint128", "uint256", ], [ @@ -158,6 +196,7 @@ def hash_offer(o): bool(o["reduceOnly"]), int(o["maxUnits"]), int(o["maxAssets"]), + int(o["continuousFeeCap"]), ], ) ) @@ -215,6 +254,8 @@ def main(): print("usage: python create_certificate.py ", file=sys.stderr) sys.exit(2) + _check_typehashes() + with open(sys.argv[1]) as f: proofs = json.load(f) diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index c00b1f1c8..4c4844f10 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -7,6 +7,7 @@ "verify": "Midnight:certora/specs/OfferTreeMembership.spec", "solc": "solc-0.8.34", "solc_via_ir": true, + "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, "loop_iter": 3, diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf index d88336857..d0b8fb08b 100644 --- a/certora/confs/OfferTreeWellFormed.conf +++ b/certora/confs/OfferTreeWellFormed.conf @@ -5,6 +5,7 @@ "verify": "OfferTree:certora/specs/OfferTreeWellFormed.spec", "solc": "solc-0.8.34", "solc_via_ir": true, + "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, "loop_iter": 3, diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index f25185128..f4957a592 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -28,6 +28,7 @@ struct Leaf { bool reduceOnly; uint256 maxUnits; uint256 maxAssets; + uint256 continuousFeeCap; } contract OfferTree { @@ -75,6 +76,7 @@ contract OfferTree { l.reduceOnly = offer.reduceOnly; l.maxUnits = offer.maxUnits; l.maxAssets = offer.maxAssets; + l.continuousFeeCap = offer.continuousFeeCap; n.hashNode = id; } @@ -141,7 +143,8 @@ contract OfferTree { l.ratifier, l.reduceOnly, l.maxUnits, - l.maxAssets + l.maxAssets, + l.continuousFeeCap ) ); } From b8c5a248de8343c76597b999623dce028b1c3fc3 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Tue, 21 Jul 2026 23:14:27 +0200 Subject: [PATCH 040/159] Improved multiplication overflow check Allow mulDiv(position.collateral, oracle.price(), ORACLE_PRICE_SCALE) to overflow. Every other mulDiv is checked that the overflow does not cause a revert. We no longer restrict price to uint128, instead only reverts due to position.collateral*oracle.price() >= 2^256 are not checked. --- certora/specs/NoMultiplicationOverflow.spec | 98 +++++++++++++++++---- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/certora/specs/NoMultiplicationOverflow.spec b/certora/specs/NoMultiplicationOverflow.spec index a3cd69a4c..5194ff020 100644 --- a/certora/specs/NoMultiplicationOverflow.spec +++ b/certora/specs/NoMultiplicationOverflow.spec @@ -1,7 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -// Proves that successful calls do not overflow in mulDivDown or mulDivUp, given the oracle price is bounded. +// Proves that the onlye overflows in mulDivDown and mulDivUp that can cause a revert are +// the ones that compute the value of a collateral against the oracle price. These can +// only overflow if the collateral is priced at more than max_uint128 debt units, which is +// a documented limitation. + +// Strictly speaking, other mulDivDown/mulDivUp may revert due to overflow. This spec +// checks for overflows at the end, showing that if there is no other reason the +// call would have reverted the mulDiv didn't overflow. Thus the mulDiv did not +// singlehandedly cause the revert. using Utils as Utils; @@ -10,9 +18,8 @@ methods { function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - // Oracle integration assumption: every (collateralAmount * oraclePrice) fits in uint256. - // Storage collateral is uint128, so boundedPrice enforces the product bound against max_uint128. - function _.price() external => boundedPrice(calledContract) expect(uint256); + // Deterministic summary for oracle price + function _.price() external => getOraclePrice(calledContract) expect(uint256); // Deterministic toId: links call-site markets to validated state from touchMarket. function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); @@ -34,6 +41,12 @@ persistent ghost bool mulOverflow; persistent ghost maxLifGhost(uint256, uint256) returns uint256; +ghost oraclePriceGhost(address) returns uint256; + +ghost uint256 lastOraclePrice; + +ghost uint256 lastCollateralAmount; + definition WAD() returns uint256 = 10 ^ 18; definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; @@ -48,10 +61,15 @@ function summaryToId(Midnight.Market market) returns (bytes32) { return Utils.hashMarket(market); } -// Bound every storage collateral (uint128) * oracle price product. -function boundedPrice(address oracle) returns uint256 { - uint256 price; - require to_mathint(price) * max_uint128 + ORACLE_PRICE_SCALE() - 1 <= max_uint256, "same as assuming that collateral * price <= uint256 with mulDivUp rounding headroom"; +// hook to remember the last queried collateral amount. +hook Sload uint128 value position[KEY bytes32 id][KEY address user].collateral[INDEX uint256 collateralIndex] { + lastCollateralAmount = value; +} + +// internal function to remember the last queried oracle price. +function getOraclePrice(address oracle) returns uint256 { + uint256 price = oraclePriceGhost(oracle); + lastOraclePrice = price; return price; } @@ -63,12 +81,24 @@ function boundedTickPrice() returns uint256 { } function mulDivDownSummary(uint256 x, uint256 y, uint256 d) returns uint256 { - mathint product = to_mathint(x) * y; - if (d != 0 && x * y >= 2 ^ 256) { - mulOverflow = true; + uint256 result; + mathint product = x * y; + if (product > max_uint256) { + // overflow in mulDivDown + if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { + // we explicitly allow the revert when some user's collateral is priced at too many debt units + // this asserts double-checks that this only happens in this case. + // gap: here we assume that collateral and oracle price match. + assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; + revert(); + } else { + // other overflows are checked at the end that they didn't cause a revert. + mulOverflow = true; + return result; + } } - uint256 result; + // These requires are proved for the no-overflow case. require d > 0 => result * d <= product, "proven in MulDiv.spec (mulDivDownRoundsDown)"; require d > 0 => y <= d => result <= x, "proven in MulDiv.spec (mulDivArgumentLesserThanDenominator)"; require d > 0 => x <= d => result <= y, "proven in MulDiv.spec (mulDivArgumentLesserThanDenominator)"; @@ -77,12 +107,25 @@ function mulDivDownSummary(uint256 x, uint256 y, uint256 d) returns uint256 { } function mulDivUpSummary(uint256 x, uint256 y, uint256 d) returns uint256 { + uint256 result; mathint product = x * y; - if (d != 0 && x * y + d - 1 >= 2 ^ 256) { - mulOverflow = true; + if (product > max_uint256 || (d > 0 && product + d - 1 > max_uint256)) { + // overflow in mulDivUp + if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { + // we explicitly allow the revert when some user's collateral is priced at too many debt units + // this asserts double-checks that this only happens in this case. + // gap: here we assume that collateral and oracle price match. + assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; + revert(); + } else { + // other overflows are checked at the end that they didn't cause a revert. + mulOverflow = true; + assert false; + return result; + } } - uint256 result; + // These requires are proved for the no-overflow case. require d > 0 => result * d <= product + d - 1, "proven in MulDiv.spec (mulDivUpUpperBound)"; require d > 0 => y <= d => result <= x, "proven in MulDiv.spec (mulDivArgumentLesserThanDenominator)"; require d > 0 => x <= d => result <= y, "proven in MulDiv.spec (mulDivArgumentLesserThanDenominator)"; @@ -93,7 +136,7 @@ function mulDivUpSummary(uint256 x, uint256 y, uint256 d) returns uint256 { /// RULES /// // Normal calls intentionally scope this proof to non-reverting executions. -// The updatePositionView and isHealthy have dedicated rules. +// The updatePositionView and isHealthy have dedicated rules to ensure market and id match. rule noMultiplicationOverflow(method f, env e, calldataarg args) filtered { f -> f.selector != sig:isHealthy(Midnight.Market, bytes32, address).selector && f.selector != sig:updatePositionView(Midnight.Market, bytes32, address).selector } { require !mulOverflow, "prestate: no overflow before call"; f(e, args); @@ -113,3 +156,26 @@ rule noMultiplicationOverflowUpdatePositionView(env e, Midnight.Market market, b updatePositionView(e, market, id, user); assert !mulOverflow; } + +rule noMultiplicationOverflowTake(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { + require !mulOverflow, "prestate: no overflow before call"; + require units < 2^129, "ensured by the toUint128 casts on units - buyerCreditIncrease and buyerCreditIncrease"; + take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); + assert !mulOverflow; +} + +rule noMultiplicationOverflowWithdraw(env e, Midnight.Market market, uint256 units, address onBehalf, address receiver) { + require !mulOverflow, "prestate: no overflow before call"; + require units < 2^128, "ensured by the toUint128 casts on units"; + withdraw(e, market, units, onBehalf, receiver); + assert !mulOverflow; +} + +rule noMultiplicationOverflowLiquidate(env e, bytes32 id, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + require !mulOverflow, "prestate: no overflow before call"; + require id == summaryToId(market), "id corresponds to market"; + require repaidUnits < 2^128, "ensured by cast"; + require seizedAssets * oraclePriceGhost(market.collateralParams[collateralIndex].oracle) / ORACLE_PRICE_SCALE() < 2^128, "ensured by subtracting seizedAssets from collateral"; + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + assert !mulOverflow; +} From 86fd2d1980f3a5ba4680bb6274b1f9f314bba82a Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Tue, 21 Jul 2026 23:20:24 +0200 Subject: [PATCH 041/159] Remove investigation of all reverting mulDiv --- certora/specs/NoMultiplicationOverflow.spec | 24 --------------------- 1 file changed, 24 deletions(-) diff --git a/certora/specs/NoMultiplicationOverflow.spec b/certora/specs/NoMultiplicationOverflow.spec index 5194ff020..6f207d50f 100644 --- a/certora/specs/NoMultiplicationOverflow.spec +++ b/certora/specs/NoMultiplicationOverflow.spec @@ -120,7 +120,6 @@ function mulDivUpSummary(uint256 x, uint256 y, uint256 d) returns uint256 { } else { // other overflows are checked at the end that they didn't cause a revert. mulOverflow = true; - assert false; return result; } } @@ -156,26 +155,3 @@ rule noMultiplicationOverflowUpdatePositionView(env e, Midnight.Market market, b updatePositionView(e, market, id, user); assert !mulOverflow; } - -rule noMultiplicationOverflowTake(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { - require !mulOverflow, "prestate: no overflow before call"; - require units < 2^129, "ensured by the toUint128 casts on units - buyerCreditIncrease and buyerCreditIncrease"; - take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); - assert !mulOverflow; -} - -rule noMultiplicationOverflowWithdraw(env e, Midnight.Market market, uint256 units, address onBehalf, address receiver) { - require !mulOverflow, "prestate: no overflow before call"; - require units < 2^128, "ensured by the toUint128 casts on units"; - withdraw(e, market, units, onBehalf, receiver); - assert !mulOverflow; -} - -rule noMultiplicationOverflowLiquidate(env e, bytes32 id, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { - require !mulOverflow, "prestate: no overflow before call"; - require id == summaryToId(market), "id corresponds to market"; - require repaidUnits < 2^128, "ensured by cast"; - require seizedAssets * oraclePriceGhost(market.collateralParams[collateralIndex].oracle) / ORACLE_PRICE_SCALE() < 2^128, "ensured by subtracting seizedAssets from collateral"; - liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert !mulOverflow; -} From a613bc8d404886203f5a4f20c6f84d2ac82a9d79 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Tue, 21 Jul 2026 23:36:38 +0200 Subject: [PATCH 042/159] Rewording of comments --- certora/specs/NoMultiplicationOverflow.spec | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/certora/specs/NoMultiplicationOverflow.spec b/certora/specs/NoMultiplicationOverflow.spec index 6f207d50f..1e96efe4b 100644 --- a/certora/specs/NoMultiplicationOverflow.spec +++ b/certora/specs/NoMultiplicationOverflow.spec @@ -1,15 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -// Proves that the onlye overflows in mulDivDown and mulDivUp that can cause a revert are -// the ones that compute the value of a collateral against the oracle price. These can -// only overflow if the collateral is priced at more than max_uint128 debt units, which is -// a documented limitation. - -// Strictly speaking, other mulDivDown/mulDivUp may revert due to overflow. This spec -// checks for overflows at the end, showing that if there is no other reason the -// call would have reverted the mulDiv didn't overflow. Thus the mulDiv did not -// singlehandedly cause the revert. +// Proves that the only overflows in mulDivDown and mulDivUp that can cause a revert are +// the ones that compute the value of a collateral against the oracle price. +// These can only overflow if the collateral is priced at more than max_uint128 debt units, +// which is documented in Midnight.sol. + +// Strictly speaking, other mulDivDown/mulDivUp may revert due to overflow, e.g., +// for withdraw a mulDiv can revert for very large values of units > 2^128. +// However, this would result in a different revert, if the mulDiv is never called. +// This spec checks for overflows at the end, showing that if there is no other reason the +// call would have reverted the mulDiv didn't overflow. +// Thus the mulDiv did not singlehandedly cause the revert. using Utils as Utils; @@ -88,7 +90,7 @@ function mulDivDownSummary(uint256 x, uint256 y, uint256 d) returns uint256 { if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { // we explicitly allow the revert when some user's collateral is priced at too many debt units // this asserts double-checks that this only happens in this case. - // gap: here we assume that collateral and oracle price match. + // gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; revert(); } else { @@ -114,7 +116,7 @@ function mulDivUpSummary(uint256 x, uint256 y, uint256 d) returns uint256 { if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { // we explicitly allow the revert when some user's collateral is priced at too many debt units // this asserts double-checks that this only happens in this case. - // gap: here we assume that collateral and oracle price match. + // gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; revert(); } else { From 8da8e320d13d61153337440e859127572572b955 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Tue, 21 Jul 2026 23:42:09 +0200 Subject: [PATCH 043/159] More comment refinement --- certora/specs/NoMultiplicationOverflow.spec | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/certora/specs/NoMultiplicationOverflow.spec b/certora/specs/NoMultiplicationOverflow.spec index 1e96efe4b..27b310920 100644 --- a/certora/specs/NoMultiplicationOverflow.spec +++ b/certora/specs/NoMultiplicationOverflow.spec @@ -11,7 +11,7 @@ // However, this would result in a different revert, if the mulDiv is never called. // This spec checks for overflows at the end, showing that if there is no other reason the // call would have reverted the mulDiv didn't overflow. -// Thus the mulDiv did not singlehandedly cause the revert. +// Thus, the mulDiv did not singlehandedly cause the revert. using Utils as Utils; @@ -88,9 +88,9 @@ function mulDivDownSummary(uint256 x, uint256 y, uint256 d) returns uint256 { if (product > max_uint256) { // overflow in mulDivDown if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { - // we explicitly allow the revert when some user's collateral is priced at too many debt units - // this asserts double-checks that this only happens in this case. - // gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. + // Explicitly allow to revert when some user's collateral is priced at too many debt units + // This assert double-checks that a revert only happens in this case. + // Gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; revert(); } else { @@ -114,9 +114,9 @@ function mulDivUpSummary(uint256 x, uint256 y, uint256 d) returns uint256 { if (product > max_uint256 || (d > 0 && product + d - 1 > max_uint256)) { // overflow in mulDivUp if (x == lastCollateralAmount && y == lastOraclePrice && d == ORACLE_PRICE_SCALE()) { - // we explicitly allow the revert when some user's collateral is priced at too many debt units - // this asserts double-checks that this only happens in this case. - // gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. + // Explicitly allow to revert when some user's collateral is priced at too many debt units + // This assert double-checks that a revert only happens in this case. + // Gap: here we assume that collateral and oracle price match. A bug where the wrong collateral index is used for the oracle is not detected by this spec. assert lastCollateralAmount * lastOraclePrice / ORACLE_PRICE_SCALE() > max_uint128, "collateral worth more than max_uint128 debt units"; revert(); } else { From 80eec16ca96edca73a7860c0a5498c281c018993 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:54:05 +0200 Subject: [PATCH 044/159] blue fallback rolling first iteration --- src/periphery/README.md | 12 + .../BlueFallbackRolling.sol | 96 ++++++++ .../IBlueFallbackRolling.sol | 54 +++++ src/periphery/libraries/SafeApproveLib.sol | 30 +++ test/BlueFallbackRollingTest.sol | 229 ++++++++++++++++++ 5 files changed, 421 insertions(+) create mode 100644 src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol create mode 100644 src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol create mode 100644 src/periphery/libraries/SafeApproveLib.sol create mode 100644 test/BlueFallbackRollingTest.sol diff --git a/src/periphery/README.md b/src/periphery/README.md index f402ad2bd..c970c2081 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -21,6 +21,18 @@ The owner is included in the creation code and combined with the salt, so differ The factory records callbacks in `callbackOf` and `isBlueBuyCallback`. +### `BlueFallbackRolling` + +Permissionlessly refinances a borrower's Midnight debt into a user-selected Morpho Blue market once the Midnight market +reaches the configured start timestamp. It supplies the selected collateral to Blue through a callback, borrows against +it to repay Midnight, and rewards the caller from the additional Blue borrow. Rolls may migrate all debt and collateral +or a proportional partial amount. + +Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight +and Blue. Each configuration selects a Blue market, start timestamp, and caller incentive, and can later be disabled. +The caller incentive is a percentage of the debt and is capped at 100%. A roll requires the borrower to have exactly +one activated Midnight collateral, matching the collateral token of the configured Blue market. + ### `EcrecoverAuthorizer` Lets an address grant or revoke a Midnight authorization using an EIP-712 signature. diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol new file mode 100644 index 000000000..aded13672 --- /dev/null +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity 0.8.34; + +import {IMorpho, Id, MarketParams} from "../../../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {MarketParamsLib} from "../../../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; +import {IMidnight, Market} from "../../interfaces/IMidnight.sol"; +import {WAD} from "../../libraries/ConstantsLib.sol"; +import {IdLib} from "../../libraries/IdLib.sol"; +import {SafeTransferLib} from "../../libraries/SafeTransferLib.sol"; +import {UtilsLib} from "../../libraries/UtilsLib.sol"; +import {IBlueFallbackRolling} from "./IBlueFallbackRolling.sol"; +import {SafeApproveLib} from "../libraries/SafeApproveLib.sol"; + +/// @dev Users must authorize this contract on both Midnight and Blue before their debt can be rolled. +contract BlueFallbackRolling is IBlueFallbackRolling { + using MarketParamsLib for MarketParams; + using UtilsLib for uint128; + + address public immutable override MIDNIGHT; + address public immutable override BLUE; + + mapping(address user => mapping(bytes32 configId => bool)) public override isConfig; + + constructor(address _midnight, address _blue) { + MIDNIGHT = _midnight; + BLUE = _blue; + } + + /// @param incentive The caller incentive as a WAD-scaled percentage of the debt rolled. + function setConfig(bytes32 midnightMarketId, bytes32 blueMarketId, uint64 start, uint64 incentive, bool enabled) + external + override + { + require(incentive <= WAD, IncentiveTooHigh()); + + isConfig[msg.sender][keccak256(abi.encode(midnightMarketId, blueMarketId, start, incentive))] = enabled; + + emit SetConfig(msg.sender, midnightMarketId, blueMarketId, start, incentive, enabled); + } + + function roll( + Market memory midnightMarket, + MarketParams memory blueMarketParams, + address user, + uint64 start, + uint64 incentive, + uint256 assets + ) external override { + bytes32 midnightMarketId = IdLib.toId(midnightMarket); + bytes32 blueMarketId = Id.unwrap(blueMarketParams.id()); + require( + isConfig[user][keccak256(abi.encode(midnightMarketId, blueMarketId, start, incentive))], NotConfigured() + ); + require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); + require(block.timestamp >= start, NotStarted()); + uint128 collateralBitmap = IMidnight(MIDNIGHT).collateralBitmap(midnightMarketId, user); + require(UtilsLib.countBits(collateralBitmap) == 1, IncorrectActivatedCollateral()); + uint256 collateralIndex = UtilsLib.msb(collateralBitmap); + require( + blueMarketParams.collateralToken == midnightMarket.collateralParams[collateralIndex].token, + InconsistentCollateralToken() + ); + + // Round in favor of the Midnight position. + uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightMarketId, user, collateralIndex) + .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightMarketId, user)); + // Round in favor of the borrower. + uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentive, WAD); + + emit Roll(msg.sender, user, midnightMarketId, blueMarketId, assets, collateralAssets, incentiveAssets); + + bytes memory data = abi.encode(midnightMarket, blueMarketParams, collateralIndex, assets, incentiveAssets, user); + IMorpho(BLUE).supplyCollateral(blueMarketParams, collateralAssets, user, data); + if (incentiveAssets > 0) SafeTransferLib.safeTransfer(midnightMarket.loanToken, msg.sender, incentiveAssets); + } + + function onMorphoSupplyCollateral(uint256 collateralAssets, bytes calldata data) external { + require(msg.sender == BLUE, NotBlue()); + + ( + Market memory midnightMarket, + MarketParams memory blueMarketParams, + uint256 collateralIndex, + uint256 assets, + uint256 incentiveAssets, + address user + ) = abi.decode(data, (Market, MarketParams, uint256, uint256, uint256, address)); + + IMorpho(BLUE).borrow(blueMarketParams, assets + incentiveAssets, 0, user, address(this)); + SafeApproveLib.forceApproveMax(midnightMarket.loanToken, MIDNIGHT); + IMidnight(MIDNIGHT).repay(midnightMarket, assets, user, address(0), hex""); + IMidnight(MIDNIGHT).withdrawCollateral(midnightMarket, collateralIndex, collateralAssets, user, address(this)); + SafeApproveLib.forceApproveMax(blueMarketParams.collateralToken, BLUE); + } +} diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol new file mode 100644 index 000000000..b0cbbb70a --- /dev/null +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity >=0.5.0; + +import {IMorphoSupplyCollateralCallback} from "../../../lib/morpho-blue/src/interfaces/IMorphoCallbacks.sol"; +import {MarketParams} from "../../../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {Market} from "../../interfaces/IMidnight.sol"; + +interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { + /// ERRORS /// + error IncentiveTooHigh(); + error IncorrectActivatedCollateral(); + error InconsistentCollateralToken(); + error InconsistentLoanToken(); + error NotBlue(); + error NotConfigured(); + error NotStarted(); + + /// EVENTS /// + event SetConfig( + address indexed user, + bytes32 indexed midnightMarketId, + bytes32 indexed blueMarketId, + uint256 start, + uint256 incentive, + bool enabled + ); + event Roll( + address indexed caller, + address indexed user, + bytes32 indexed midnightMarketId, + bytes32 blueMarketId, + uint256 debtAssets, + uint256 collateralAssets, + uint256 incentiveAssets + ); + + /// STORAGE GETTERS /// + function MIDNIGHT() external view returns (address); + function BLUE() external view returns (address); + function isConfig(address user, bytes32 configId) external view returns (bool); + + /// FUNCTIONS /// + function setConfig(bytes32 midnightMarketId, bytes32 blueMarketId, uint64 start, uint64 incentive, bool enabled) + external; + function roll( + Market memory midnightMarket, + MarketParams memory blueMarketParams, + address user, + uint64 start, + uint64 incentive, + uint256 assets + ) external; +} diff --git a/src/periphery/libraries/SafeApproveLib.sol b/src/periphery/libraries/SafeApproveLib.sol new file mode 100644 index 000000000..61f4778a5 --- /dev/null +++ b/src/periphery/libraries/SafeApproveLib.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity ^0.8.0; + +interface IERC20Approve { + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 value) external returns (bool); +} + +library SafeApproveLib { + error ApproveReturnedFalse(); + + /// @dev Skips the approval when the current allowance is already at least 2^95 - 1. + /// @dev Resets to 0 before re-approving to support USDT-like tokens. + function forceApproveMax(address token, address spender) internal { + if (IERC20Approve(token).allowance(address(this), spender) >= type(uint96).max / 2) return; + safeApprove(token, spender, 0); + safeApprove(token, spender, type(uint256).max); + } + + function safeApprove(address token, address spender, uint256 value) internal { + (bool success, bytes memory returndata) = token.call(abi.encodeCall(IERC20Approve.approve, (spender, value))); + if (!success) { + assembly ("memory-safe") { + revert(add(returndata, 0x20), mload(returndata)) + } + } + require(returndata.length == 0 || abi.decode(returndata, (bool)), ApproveReturnedFalse()); + } +} diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol new file mode 100644 index 000000000..9b18c5def --- /dev/null +++ b/test/BlueFallbackRollingTest.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity ^0.8.0; + +import {IMorpho, Id, MarketParams} from "../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {MarketParamsLib} from "../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; +import {Market, CollateralParams} from "../src/interfaces/IMidnight.sol"; +import {WAD} from "../src/libraries/ConstantsLib.sol"; +import {BlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol"; +import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol"; +import {BaseTest, LLTV, LIQUIDATION_CURSOR} from "./BaseTest.sol"; + +contract BlueFallbackRollingTest is BaseTest { + using MarketParamsLib for MarketParams; + + uint256 internal constant BLUE_LLTV = 0.86e18; + uint256 internal constant INCENTIVE = 0.001e18; + uint256 internal constant DEBT = 10_000e18; + + address internal keeper = makeAddr("keeper"); + IMorpho internal blue; + BlueFallbackRolling internal fallbackContract; + Market internal midnightMarket; + MarketParams internal blueMarketParams; + uint256 internal blueCollateralIndex; + uint64 internal start; + + function setUp() public override { + super.setUp(); + start = uint64(vm.getBlockTimestamp()); + + blue = IMorpho(deployCode("Morpho.sol", abi.encode(address(this)))); + blue.enableIrm(address(0)); + blue.enableLltv(BLUE_LLTV); + + blueMarketParams = MarketParams({ + loanToken: address(loanToken), + collateralToken: address(collateralToken1), + oracle: address(oracle1), + irm: address(0), + lltv: BLUE_LLTV + }); + blue.createMarket(blueMarketParams); + + fallbackContract = new BlueFallbackRolling(address(midnight), address(blue)); + + midnightMarket.loanToken = address(loanToken); + midnightMarket.chainId = block.chainid; + midnightMarket.midnight = address(midnight); + midnightMarket.maturity = vm.getBlockTimestamp() + 1 days; + midnightMarket.collateralParams + .push( + CollateralParams({ + token: address(collateralToken1), + lltv: LLTV, + liquidationCursor: LIQUIDATION_CURSOR, + oracle: address(oracle1) + }) + ); + midnightMarket.collateralParams + .push( + CollateralParams({ + token: address(collateralToken2), + lltv: LLTV, + liquidationCursor: LIQUIDATION_CURSOR, + oracle: address(oracle2) + }) + ); + midnightMarket.collateralParams = sortCollateralParams(midnightMarket.collateralParams); + blueCollateralIndex = midnightMarket.collateralParams[0].token == address(collateralToken1) ? 0 : 1; + + collateralize(midnightMarket, borrower, DEBT, blueCollateralIndex); + setupMarket(midnightMarket, DEBT); + + deal(address(loanToken), address(this), 2 * DEBT); + loanToken.approve(address(blue), type(uint256).max); + blue.supply(blueMarketParams, 2 * DEBT, 0, lender, hex""); + + vm.prank(borrower); + midnight.setIsAuthorized(address(fallbackContract), true, borrower); + vm.prank(borrower); + blue.setAuthorization(address(fallbackContract), true); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), true + ); + } + + function testAnyoneCanRollBorrowerToBlue() public { + uint256 midnightCollateral = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + + uint256 incentiveAssets = DEBT * INCENTIVE / WAD; + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); + assertEq(blue.position(blueMarketParams.id(), borrower).collateral, midnightCollateral); + assertGt(blue.position(blueMarketParams.id(), borrower).borrowShares, 0); + assertEq(loanToken.balanceOf(keeper), incentiveAssets); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + } + + function testAnyoneCanPartiallyRollBorrowerToBlue() public { + uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + uint256 debtAssets = DEBT / 2; + uint256 collateralAssets = totalCollateralAssets * debtAssets / DEBT; + + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), debtAssets); + + uint256 incentiveAssets = debtAssets * INCENTIVE / WAD; + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - debtAssets); + assertEq( + midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), + totalCollateralAssets - collateralAssets + ); + assertEq(blue.position(blueMarketParams.id(), borrower).collateral, collateralAssets); + assertGt(blue.position(blueMarketParams.id(), borrower).borrowShares, 0); + assertEq(loanToken.balanceOf(keeper), incentiveAssets); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + } + + function testCannotRollBeforeStart() public { + uint64 futureStart = uint64(vm.getBlockTimestamp() + 1); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, uint64(INCENTIVE), true + ); + + vm.expectRevert(IBlueFallbackRolling.NotStarted.selector); + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, futureStart, uint64(INCENTIVE), DEBT); + } + + function testRollRevertsForUnconfiguredBlueMarket() public { + blueMarketParams.oracle = makeAddr("otherOracle"); + + vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + } + + function testRollRevertsForInconsistentLoanToken() public { + blueMarketParams.loanToken = makeAddr("otherLoanToken"); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), true + ); + + vm.expectRevert(IBlueFallbackRolling.InconsistentLoanToken.selector); + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + } + + function testRollRevertsForMultipleActivatedCollaterals() public { + collateralize(midnightMarket, borrower, DEBT, 1 - blueCollateralIndex); + + vm.expectRevert(IBlueFallbackRolling.IncorrectActivatedCollateral.selector); + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + } + + function testRollRevertsWhenActivatedCollateralDoesNotMatchBlue() public { + uint256 otherCollateralIndex = 1 - blueCollateralIndex; + collateralize(midnightMarket, borrower, DEBT, otherCollateralIndex); + uint256 blueCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + vm.prank(borrower); + midnight.withdrawCollateral(midnightMarket, blueCollateralIndex, blueCollateralAssets, borrower, borrower); + + vm.expectRevert(IBlueFallbackRolling.InconsistentCollateralToken.selector); + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + } + + function testSupplyCollateralCallbackRevertsIfCallerIsNotBlue() public { + uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + vm.expectRevert(IBlueFallbackRolling.NotBlue.selector); + fallbackContract.onMorphoSupplyCollateral( + collateralAssets, + abi.encode(midnightMarket, blueMarketParams, blueCollateralIndex, DEBT, DEBT * INCENTIVE / WAD, borrower) + ); + } + + function testSetConfig() public view { + assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); + } + + function testSetConfigRevertsForTooLargeIncentive() public { + uint64 incentive = uint64(WAD + 1); + + vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, incentive, true); + } + + function testSetConfigAllowsOneIncentive() public { + vm.prank(borrower); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(WAD), true); + + assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(WAD)))); + } + + function testSetConfigCanDisable() public { + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), false + ); + + assertFalse(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); + + vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + } + + function testSetConfigDoesNotReplaceOtherConfig() public { + uint64 otherStart = start + 1; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, uint64(WAD), true + ); + + assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); + assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, uint64(WAD)))); + } + + function configId(uint64 _start, uint64 incentive) internal view returns (bytes32) { + return keccak256(abi.encode(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, incentive)); + } +} From 2fe1897df28fcd9344ccb67ecd8ba828d21879fd Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:14:30 +0200 Subject: [PATCH 045/159] nit --- .../BlueFallbackRolling.sol | 22 +++++++++---------- .../IBlueFallbackRolling.sol | 11 +++++----- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index aded13672..25878ca94 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,15 +28,15 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @param incentive The caller incentive as a WAD-scaled percentage of the debt rolled. - function setConfig(bytes32 midnightMarketId, bytes32 blueMarketId, uint64 start, uint64 incentive, bool enabled) + function setConfig(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive, bool enabled) external override { require(incentive <= WAD, IncentiveTooHigh()); - isConfig[msg.sender][keccak256(abi.encode(midnightMarketId, blueMarketId, start, incentive))] = enabled; + isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, incentive))] = enabled; - emit SetConfig(msg.sender, midnightMarketId, blueMarketId, start, incentive, enabled); + emit SetConfig(msg.sender, midnightId, blueId, start, incentive, enabled); } function roll( @@ -47,14 +47,12 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint64 incentive, uint256 assets ) external override { - bytes32 midnightMarketId = IdLib.toId(midnightMarket); - bytes32 blueMarketId = Id.unwrap(blueMarketParams.id()); - require( - isConfig[user][keccak256(abi.encode(midnightMarketId, blueMarketId, start, incentive))], NotConfigured() - ); + bytes32 midnightId = IdLib.toId(midnightMarket); + bytes32 blueId = Id.unwrap(blueMarketParams.id()); + require(isConfig[user][keccak256(abi.encode(midnightId, blueId, start, incentive))], NotConfigured()); require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); require(block.timestamp >= start, NotStarted()); - uint128 collateralBitmap = IMidnight(MIDNIGHT).collateralBitmap(midnightMarketId, user); + uint128 collateralBitmap = IMidnight(MIDNIGHT).collateralBitmap(midnightId, user); require(UtilsLib.countBits(collateralBitmap) == 1, IncorrectActivatedCollateral()); uint256 collateralIndex = UtilsLib.msb(collateralBitmap); require( @@ -63,12 +61,12 @@ contract BlueFallbackRolling is IBlueFallbackRolling { ); // Round in favor of the Midnight position. - uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightMarketId, user, collateralIndex) - .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightMarketId, user)); + uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) + .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); // Round in favor of the borrower. uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentive, WAD); - emit Roll(msg.sender, user, midnightMarketId, blueMarketId, assets, collateralAssets, incentiveAssets); + emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); bytes memory data = abi.encode(midnightMarket, blueMarketParams, collateralIndex, assets, incentiveAssets, user); IMorpho(BLUE).supplyCollateral(blueMarketParams, collateralAssets, user, data); diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index b0cbbb70a..7450827e3 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -19,8 +19,8 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// EVENTS /// event SetConfig( address indexed user, - bytes32 indexed midnightMarketId, - bytes32 indexed blueMarketId, + bytes32 indexed midnightId, + bytes32 indexed blueId, uint256 start, uint256 incentive, bool enabled @@ -28,8 +28,8 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { event Roll( address indexed caller, address indexed user, - bytes32 indexed midnightMarketId, - bytes32 blueMarketId, + bytes32 indexed midnightId, + bytes32 blueId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets @@ -41,8 +41,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { function isConfig(address user, bytes32 configId) external view returns (bool); /// FUNCTIONS /// - function setConfig(bytes32 midnightMarketId, bytes32 blueMarketId, uint64 start, uint64 incentive, bool enabled) - external; + function setConfig(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive, bool enabled) external; function roll( Market memory midnightMarket, MarketParams memory blueMarketParams, From 58cf26e9d56293596e9ef0f27271f876d5643771 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:19:38 +0200 Subject: [PATCH 046/159] lint --- test/BlueFallbackRollingTest.sol | 51 ++++++++++++++------------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 9b18c5def..5928b14eb 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -14,7 +14,8 @@ contract BlueFallbackRollingTest is BaseTest { using MarketParamsLib for MarketParams; uint256 internal constant BLUE_LLTV = 0.86e18; - uint256 internal constant INCENTIVE = 0.001e18; + uint64 internal constant INCENTIVE = 0.001e18; + uint64 internal constant MAX_INCENTIVE = 1e18; uint256 internal constant DEBT = 10_000e18; address internal keeper = makeAddr("keeper"); @@ -81,16 +82,14 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(borrower); blue.setAuthorization(address(fallbackContract), true); vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), true - ); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, true); } function testAnyoneCanRollBorrowerToBlue() public { uint256 midnightCollateral = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); uint256 incentiveAssets = DEBT * INCENTIVE / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), 0); @@ -107,7 +106,7 @@ contract BlueFallbackRollingTest is BaseTest { uint256 collateralAssets = totalCollateralAssets * debtAssets / DEBT; vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), debtAssets); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, debtAssets); uint256 incentiveAssets = debtAssets * INCENTIVE / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - debtAssets); @@ -124,13 +123,11 @@ contract BlueFallbackRollingTest is BaseTest { function testCannotRollBeforeStart() public { uint64 futureStart = uint64(vm.getBlockTimestamp() + 1); vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, uint64(INCENTIVE), true - ); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, INCENTIVE, true); vm.expectRevert(IBlueFallbackRolling.NotStarted.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, futureStart, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, futureStart, INCENTIVE, DEBT); } function testRollRevertsForUnconfiguredBlueMarket() public { @@ -138,19 +135,17 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); } function testRollRevertsForInconsistentLoanToken() public { blueMarketParams.loanToken = makeAddr("otherLoanToken"); vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), true - ); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, true); vm.expectRevert(IBlueFallbackRolling.InconsistentLoanToken.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); } function testRollRevertsForMultipleActivatedCollaterals() public { @@ -158,7 +153,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncorrectActivatedCollateral.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); } function testRollRevertsWhenActivatedCollateralDoesNotMatchBlue() public { @@ -170,7 +165,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.InconsistentCollateralToken.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); } function testSupplyCollateralCallbackRevertsIfCallerIsNotBlue() public { @@ -183,11 +178,11 @@ contract BlueFallbackRollingTest is BaseTest { } function testSetConfig() public view { - assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); } function testSetConfigRevertsForTooLargeIncentive() public { - uint64 incentive = uint64(WAD + 1); + uint64 incentive = MAX_INCENTIVE + 1; vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, incentive, true); @@ -195,32 +190,30 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(WAD), true); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, MAX_INCENTIVE, true); - assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(WAD)))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, MAX_INCENTIVE))); } function testSetConfigCanDisable() public { vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, uint64(INCENTIVE), false - ); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, false); - assertFalse(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); + assertFalse(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, uint64(INCENTIVE), DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); } function testSetConfigDoesNotReplaceOtherConfig() public { uint64 otherStart = start + 1; vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, uint64(WAD), true + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, MAX_INCENTIVE, true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, uint64(INCENTIVE)))); - assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, uint64(WAD)))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, MAX_INCENTIVE))); } function configId(uint64 _start, uint64 incentive) internal view returns (bytes32) { From f112dec91450327061a1d94e9d611ef4a3b72810 Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 29 Jul 2026 17:00:26 +0200 Subject: [PATCH 047/159] refactor: roll event --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 25878ca94..b8b2b45f4 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -66,11 +66,11 @@ contract BlueFallbackRolling is IBlueFallbackRolling { // Round in favor of the borrower. uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentive, WAD); - emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); - bytes memory data = abi.encode(midnightMarket, blueMarketParams, collateralIndex, assets, incentiveAssets, user); IMorpho(BLUE).supplyCollateral(blueMarketParams, collateralAssets, user, data); if (incentiveAssets > 0) SafeTransferLib.safeTransfer(midnightMarket.loanToken, msg.sender, incentiveAssets); + + emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); } function onMorphoSupplyCollateral(uint256 collateralAssets, bytes calldata data) external { From 99aefcc9cac81eeb6876daeea643fc04f2753453 Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 29 Jul 2026 17:14:08 +0200 Subject: [PATCH 048/159] refactor: undo --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index b8b2b45f4..25878ca94 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -66,11 +66,11 @@ contract BlueFallbackRolling is IBlueFallbackRolling { // Round in favor of the borrower. uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentive, WAD); + emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); + bytes memory data = abi.encode(midnightMarket, blueMarketParams, collateralIndex, assets, incentiveAssets, user); IMorpho(BLUE).supplyCollateral(blueMarketParams, collateralAssets, user, data); if (incentiveAssets > 0) SafeTransferLib.safeTransfer(midnightMarket.loanToken, msg.sender, incentiveAssets); - - emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); } function onMorphoSupplyCollateral(uint256 collateralAssets, bytes calldata data) external { From 7942e0dfdf50c9f2f4a1492bdf3c27d30112eca8 Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 5 Aug 2026 18:17:15 +0200 Subject: [PATCH 049/159] doc --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 25878ca94..b9782d628 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -27,7 +27,9 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } + /// @param start The start time of the rolling period. /// @param incentive The caller incentive as a WAD-scaled percentage of the debt rolled. + /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. function setConfig(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive, bool enabled) external override From 9ba4fdb61e98abad1d9e3cdeb4eb87a41e4d27f6 Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 5 Aug 2026 18:51:52 +0200 Subject: [PATCH 050/159] feat: auction --- .../BlueFallbackRolling.sol | 52 +++- .../IBlueFallbackRolling.sol | 20 +- test/BlueFallbackRollingTest.sol | 225 +++++++++++++++--- 3 files changed, 256 insertions(+), 41 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index b9782d628..854f0a94b 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,17 +28,41 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @param start The start time of the rolling period. - /// @param incentive The caller incentive as a WAD-scaled percentage of the debt rolled. + /// @param incentiveAtStart The caller incentive at `start`, as a WAD-scaled percentage of the debt rolled. + /// @param incentiveAtMaturity The caller incentive at the Midnight market's maturity, as a WAD-scaled percentage of + /// the debt rolled. The incentive is auctioned off between the two: see `incentive`. /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. - function setConfig(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive, bool enabled) - external - override - { - require(incentive <= WAD, IncentiveTooHigh()); + function setConfig( + bytes32 midnightId, + bytes32 blueId, + uint64 start, + uint64 incentiveAtStart, + uint64 incentiveAtMaturity, + bool enabled + ) external override { + require(incentiveAtStart <= incentiveAtMaturity, IncentiveNotIncreasing()); + require(incentiveAtMaturity <= WAD, IncentiveTooHigh()); + + isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity))] = + enabled; - isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, incentive))] = enabled; + emit SetConfig(msg.sender, midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity, enabled); + } - emit SetConfig(msg.sender, midnightId, blueId, start, incentive, enabled); + /// @notice The caller incentive at the current timestamp, as a WAD-scaled percentage of the debt rolled. + /// @dev The incentive is auctioned off: it grows linearly from `incentiveAtStart` at `start` to + /// `incentiveAtMaturity` at `maturity`, and stays at `incentiveAtMaturity` afterwards. + function incentive(uint64 start, uint256 maturity, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + public + view + override + returns (uint256) + { + if (block.timestamp >= maturity) return incentiveAtMaturity; + if (block.timestamp <= start) return incentiveAtStart; + // Round in favor of the borrower. + return incentiveAtStart + + UtilsLib.mulDivDown(incentiveAtMaturity - incentiveAtStart, block.timestamp - start, maturity - start); } function roll( @@ -46,12 +70,16 @@ contract BlueFallbackRolling is IBlueFallbackRolling { MarketParams memory blueMarketParams, address user, uint64 start, - uint64 incentive, + uint64 incentiveAtStart, + uint64 incentiveAtMaturity, uint256 assets ) external override { bytes32 midnightId = IdLib.toId(midnightMarket); bytes32 blueId = Id.unwrap(blueMarketParams.id()); - require(isConfig[user][keccak256(abi.encode(midnightId, blueId, start, incentive))], NotConfigured()); + require( + isConfig[user][keccak256(abi.encode(midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity))], + NotConfigured() + ); require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); require(block.timestamp >= start, NotStarted()); uint128 collateralBitmap = IMidnight(MIDNIGHT).collateralBitmap(midnightId, user); @@ -66,7 +94,9 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); // Round in favor of the borrower. - uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentive, WAD); + uint256 incentiveAssets = UtilsLib.mulDivDown( + assets, incentive(start, midnightMarket.maturity, incentiveAtStart, incentiveAtMaturity), WAD + ); emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index 7450827e3..303529afc 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -8,6 +8,7 @@ import {Market} from "../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// + error IncentiveNotIncreasing(); error IncentiveTooHigh(); error IncorrectActivatedCollateral(); error InconsistentCollateralToken(); @@ -22,7 +23,8 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { bytes32 indexed midnightId, bytes32 indexed blueId, uint256 start, - uint256 incentive, + uint256 incentiveAtStart, + uint256 incentiveAtMaturity, bool enabled ); event Roll( @@ -41,13 +43,25 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { function isConfig(address user, bytes32 configId) external view returns (bool); /// FUNCTIONS /// - function setConfig(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive, bool enabled) external; + function setConfig( + bytes32 midnightId, + bytes32 blueId, + uint64 start, + uint64 incentiveAtStart, + uint64 incentiveAtMaturity, + bool enabled + ) external; function roll( Market memory midnightMarket, MarketParams memory blueMarketParams, address user, uint64 start, - uint64 incentive, + uint64 incentiveAtStart, + uint64 incentiveAtMaturity, uint256 assets ) external; + function incentive(uint64 start, uint256 maturity, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + external + view + returns (uint256); } diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 5928b14eb..ea0a79604 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -14,7 +14,8 @@ contract BlueFallbackRollingTest is BaseTest { using MarketParamsLib for MarketParams; uint256 internal constant BLUE_LLTV = 0.86e18; - uint64 internal constant INCENTIVE = 0.001e18; + uint64 internal constant INCENTIVE_AT_START = 0.0002e18; + uint64 internal constant INCENTIVE_AT_MATURITY = 0.001e18; uint64 internal constant MAX_INCENTIVE = 1e18; uint256 internal constant DEBT = 10_000e18; @@ -82,16 +83,26 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(borrower); blue.setAuthorization(address(fallbackContract), true); vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, true); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + INCENTIVE_AT_START, + INCENTIVE_AT_MATURITY, + true + ); } function testAnyoneCanRollBorrowerToBlue() public { uint256 midnightCollateral = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + vm.warp(midnightMarket.maturity); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); - uint256 incentiveAssets = DEBT * INCENTIVE / WAD; + uint256 incentiveAssets = DEBT * INCENTIVE_AT_MATURITY / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), 0); assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); assertEq(blue.position(blueMarketParams.id(), borrower).collateral, midnightCollateral); @@ -104,11 +115,14 @@ contract BlueFallbackRollingTest is BaseTest { uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); uint256 debtAssets = DEBT / 2; uint256 collateralAssets = totalCollateralAssets * debtAssets / DEBT; + vm.warp(midnightMarket.maturity); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, debtAssets); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, debtAssets + ); - uint256 incentiveAssets = debtAssets * INCENTIVE / WAD; + uint256 incentiveAssets = debtAssets * INCENTIVE_AT_MATURITY / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - debtAssets); assertEq( midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), @@ -120,14 +134,110 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(loanToken.balanceOf(address(fallbackContract)), 0); } + function testIncentiveIsTheStartIncentiveBeforeAndAtStart() public view { + assertEq( + fallbackContract.incentive(start + 1, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), + INCENTIVE_AT_START + ); + assertEq( + fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), + INCENTIVE_AT_START + ); + } + + function testIncentiveGrowsLinearlyUntilMaturity(uint256 elapsed) public { + uint256 duration = midnightMarket.maturity - start; + elapsed = bound(elapsed, 0, duration); + vm.warp(start + elapsed); + + assertEq( + fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), + expectedIncentive(elapsed) + ); + } + + function testIncentiveIsFlatWhenBothBoundsAreEqual(uint256 elapsed) public { + elapsed = bound(elapsed, 0, midnightMarket.maturity - start); + vm.warp(start + elapsed); + + assertEq( + fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_START), + INCENTIVE_AT_START + ); + } + + function testIncentiveIsCappedAfterMaturity(uint256 elapsed) public { + elapsed = bound(elapsed, 0, 100 * 365 days); + vm.warp(midnightMarket.maturity + elapsed); + + assertEq( + fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), + INCENTIVE_AT_MATURITY + ); + } + + function testRollPaysTheAuctionedIncentive(uint256 elapsed) public { + elapsed = bound(elapsed, 0, midnightMarket.maturity - start); + vm.warp(start + elapsed); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); + + assertEq(loanToken.balanceOf(keeper), DEBT * expectedIncentive(elapsed) / WAD); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + + function testRollAtStartPaysTheStartIncentive() public { + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); + + assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_START / WAD); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + + /// @dev Measures the gas of a full roll: supplyCollateral on Blue, borrow on Blue, repay and + /// withdrawCollateral on Midnight, plus the incentive transfer. Rolls at maturity so the incentive is maximal. + function testGasFullRoll() public { + vm.warp(midnightMarket.maturity); + + // Copy the params to memory beforehand so the gasleft() window only covers the roll itself. + Market memory _midnightMarket = midnightMarket; + MarketParams memory _blueMarketParams = blueMarketParams; + + vm.prank(keeper); + uint256 gasBefore = gasleft(); + fallbackContract.roll( + _midnightMarket, _blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); + uint256 gasUsed = gasBefore - gasleft(); + + emit log_named_uint("Gas: full roll", gasUsed); + + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + function testCannotRollBeforeStart() public { uint64 futureStart = uint64(vm.getBlockTimestamp() + 1); vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, INCENTIVE, true); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + futureStart, + INCENTIVE_AT_START, + INCENTIVE_AT_MATURITY, + true + ); vm.expectRevert(IBlueFallbackRolling.NotStarted.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, futureStart, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, futureStart, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testRollRevertsForUnconfiguredBlueMarket() public { @@ -135,17 +245,28 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testRollRevertsForInconsistentLoanToken() public { blueMarketParams.loanToken = makeAddr("otherLoanToken"); vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, true); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + INCENTIVE_AT_START, + INCENTIVE_AT_MATURITY, + true + ); vm.expectRevert(IBlueFallbackRolling.InconsistentLoanToken.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testRollRevertsForMultipleActivatedCollaterals() public { @@ -153,7 +274,9 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncorrectActivatedCollateral.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testRollRevertsWhenActivatedCollateralDoesNotMatchBlue() public { @@ -165,7 +288,9 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.InconsistentCollateralToken.selector); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testSupplyCollateralCallbackRevertsIfCallerIsNotBlue() public { @@ -173,50 +298,96 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotBlue.selector); fallbackContract.onMorphoSupplyCollateral( collateralAssets, - abi.encode(midnightMarket, blueMarketParams, blueCollateralIndex, DEBT, DEBT * INCENTIVE / WAD, borrower) + abi.encode( + midnightMarket, + blueMarketParams, + blueCollateralIndex, + DEBT, + DEBT * INCENTIVE_AT_MATURITY / WAD, + borrower + ) ); } function testSetConfig() public view { - assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); } function testSetConfigRevertsForTooLargeIncentive() public { - uint64 incentive = MAX_INCENTIVE + 1; + uint64 incentiveAtMaturity = MAX_INCENTIVE + 1; vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, incentive, true); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE_AT_START, incentiveAtMaturity, true + ); + } + + function testSetConfigRevertsForDecreasingIncentive() public { + vm.expectRevert(IBlueFallbackRolling.IncentiveNotIncreasing.selector); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + INCENTIVE_AT_MATURITY + 1, + INCENTIVE_AT_MATURITY, + true + ); } function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, MAX_INCENTIVE, true); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, MAX_INCENTIVE, MAX_INCENTIVE, true + ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, MAX_INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, MAX_INCENTIVE, MAX_INCENTIVE))); } function testSetConfigCanDisable() public { vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE, false); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + INCENTIVE_AT_START, + INCENTIVE_AT_MATURITY, + false + ); - assertFalse(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); + assertFalse(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, INCENTIVE, DEBT); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + ); } function testSetConfigDoesNotReplaceOtherConfig() public { uint64 otherStart = start + 1; vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, MAX_INCENTIVE, true + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, MAX_INCENTIVE, MAX_INCENTIVE, true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE))); - assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, MAX_INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); + assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, MAX_INCENTIVE, MAX_INCENTIVE))); + } + + /// @dev The incentive `elapsed` seconds into the auction, interpolated between the two configured bounds. + function expectedIncentive(uint256 elapsed) internal view returns (uint256) { + uint256 duration = midnightMarket.maturity - start; + return INCENTIVE_AT_START + (INCENTIVE_AT_MATURITY - INCENTIVE_AT_START) * elapsed / duration; } - function configId(uint64 _start, uint64 incentive) internal view returns (bytes32) { - return keccak256(abi.encode(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, incentive)); + function configId(uint64 _start, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + internal + view + returns (bytes32) + { + return keccak256( + abi.encode( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, incentiveAtStart, incentiveAtMaturity + ) + ); } } From fc42bf16f64deaff9a3422da3e9e81fe32847912 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 7 Aug 2026 09:21:31 +0200 Subject: [PATCH 051/159] feat: auction end --- .../BlueFallbackRolling.sol | 39 ++-- .../IBlueFallbackRolling.sol | 12 +- test/BlueFallbackRollingFactoryTest.sol | 126 +++++++++++++ test/BlueFallbackRollingTest.sol | 177 +++++++++++------- 4 files changed, 264 insertions(+), 90 deletions(-) create mode 100644 test/BlueFallbackRollingFactoryTest.sol diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 854f0a94b..b4bb63435 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,41 +28,44 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @param start The start time of the rolling period. + /// @param end The end time of the rolling period. /// @param incentiveAtStart The caller incentive at `start`, as a WAD-scaled percentage of the debt rolled. - /// @param incentiveAtMaturity The caller incentive at the Midnight market's maturity, as a WAD-scaled percentage of - /// the debt rolled. The incentive is auctioned off between the two: see `incentive`. + /// @param incentiveAtEnd The caller incentive at `end`, as a WAD-scaled percentage of the debt rolled. The /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. function setConfig( bytes32 midnightId, bytes32 blueId, uint64 start, + uint64 end, uint64 incentiveAtStart, - uint64 incentiveAtMaturity, + uint64 incentiveAtEnd, bool enabled ) external override { - require(incentiveAtStart <= incentiveAtMaturity, IncentiveNotIncreasing()); - require(incentiveAtMaturity <= WAD, IncentiveTooHigh()); + require(start <= end, EndBeforeStart()); + require(incentiveAtStart <= incentiveAtEnd, IncentiveNotIncreasing()); + require(incentiveAtEnd <= WAD, IncentiveTooHigh()); - isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity))] = + isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))] = enabled; - emit SetConfig(msg.sender, midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity, enabled); + emit SetConfig(msg.sender, midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, enabled); } /// @notice The caller incentive at the current timestamp, as a WAD-scaled percentage of the debt rolled. - /// @dev The incentive is auctioned off: it grows linearly from `incentiveAtStart` at `start` to - /// `incentiveAtMaturity` at `maturity`, and stays at `incentiveAtMaturity` afterwards. - function incentive(uint64 start, uint256 maturity, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + /// @dev The incentive is auctioned off: it grows linearly from `incentiveAtStart` at `start` to `incentiveAtEnd` at + /// `end`, and stays at `incentiveAtEnd` afterwards. + function incentive(uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd) public view override returns (uint256) { - if (block.timestamp >= maturity) return incentiveAtMaturity; + if (block.timestamp >= end) return incentiveAtEnd; if (block.timestamp <= start) return incentiveAtStart; // Round in favor of the borrower. - return incentiveAtStart - + UtilsLib.mulDivDown(incentiveAtMaturity - incentiveAtStart, block.timestamp - start, maturity - start); + return + incentiveAtStart + + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); } function roll( @@ -70,14 +73,15 @@ contract BlueFallbackRolling is IBlueFallbackRolling { MarketParams memory blueMarketParams, address user, uint64 start, + uint64 end, uint64 incentiveAtStart, - uint64 incentiveAtMaturity, + uint64 incentiveAtEnd, uint256 assets ) external override { bytes32 midnightId = IdLib.toId(midnightMarket); bytes32 blueId = Id.unwrap(blueMarketParams.id()); require( - isConfig[user][keccak256(abi.encode(midnightId, blueId, start, incentiveAtStart, incentiveAtMaturity))], + isConfig[user][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))], NotConfigured() ); require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); @@ -94,9 +98,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); // Round in favor of the borrower. - uint256 incentiveAssets = UtilsLib.mulDivDown( - assets, incentive(start, midnightMarket.maturity, incentiveAtStart, incentiveAtMaturity), WAD - ); + uint256 incentiveAssets = + UtilsLib.mulDivDown(assets, incentive(start, end, incentiveAtStart, incentiveAtEnd), WAD); emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index 303529afc..12f55b042 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -8,6 +8,7 @@ import {Market} from "../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// + error EndBeforeStart(); error IncentiveNotIncreasing(); error IncentiveTooHigh(); error IncorrectActivatedCollateral(); @@ -23,8 +24,9 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { bytes32 indexed midnightId, bytes32 indexed blueId, uint256 start, + uint256 end, uint256 incentiveAtStart, - uint256 incentiveAtMaturity, + uint256 incentiveAtEnd, bool enabled ); event Roll( @@ -47,8 +49,9 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { bytes32 midnightId, bytes32 blueId, uint64 start, + uint64 end, uint64 incentiveAtStart, - uint64 incentiveAtMaturity, + uint64 incentiveAtEnd, bool enabled ) external; function roll( @@ -56,11 +59,12 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { MarketParams memory blueMarketParams, address user, uint64 start, + uint64 end, uint64 incentiveAtStart, - uint64 incentiveAtMaturity, + uint64 incentiveAtEnd, uint256 assets ) external; - function incentive(uint64 start, uint256 maturity, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + function incentive(uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd) external view returns (uint256); diff --git a/test/BlueFallbackRollingFactoryTest.sol b/test/BlueFallbackRollingFactoryTest.sol new file mode 100644 index 000000000..3f96e859f --- /dev/null +++ b/test/BlueFallbackRollingFactoryTest.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity ^0.8.0; + +import {Test} from "../lib/forge-std/src/Test.sol"; +import {Vm} from "../lib/forge-std/src/Vm.sol"; +import {WAD} from "../src/libraries/ConstantsLib.sol"; +import {BlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol"; +import {BlueFallbackRollingFactory} from "../src/periphery/blue-fallback-rolling/BlueFallbackRollingFactory.sol"; +import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol"; +import {IBlueFallbackRollingFactory} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRollingFactory.sol"; + +contract BlueFallbackRollingFactoryTest is Test { + address internal midnight = makeAddr("midnight"); + address internal blue = makeAddr("blue"); + address internal caller = makeAddr("caller"); + BlueFallbackRollingFactory internal factory; + + function setUp() public { + factory = new BlueFallbackRollingFactory(midnight, blue); + } + + function testConstructor() public view { + assertEq(factory.MIDNIGHT(), midnight); + assertEq(factory.BLUE(), blue); + } + + function testCreateBlueFallbackRolling(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive) public { + incentive = uint64(bound(incentive, 0, WAD)); + + vm.prank(caller); + address rollingAddress = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + BlueFallbackRolling rolling = BlueFallbackRolling(rollingAddress); + bytes32 configId = keccak256(abi.encode(midnightId, blueId, start, incentive)); + bytes32 initCodeHash = keccak256( + abi.encodePacked( + type(BlueFallbackRolling).creationCode, abi.encode(midnight, blue, midnightId, blueId, start, incentive) + ) + ); + + assertEq(rollingAddress, vm.computeCreate2Address(configId, initCodeHash, address(factory))); + assertEq(factory.blueFallbackRollingOf(configId), rollingAddress); + assertTrue(factory.isBlueFallbackRolling(rollingAddress)); + assertEq(rolling.MIDNIGHT(), midnight); + assertEq(rolling.BLUE(), blue); + assertEq(rolling.MIDNIGHT_ID(), midnightId); + assertEq(rolling.BLUE_ID(), blueId); + assertEq(rolling.START(), start); + assertEq(rolling.INCENTIVE(), incentive); + } + + function testCreateBlueFallbackRollingEmitsEvent(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive) + public + { + incentive = uint64(bound(incentive, 0, WAD)); + + vm.recordLogs(); + vm.prank(caller); + address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertEq(logs.length, 1); + assertEq(logs[0].emitter, address(factory)); + assertEq(logs[0].topics[0], IBlueFallbackRollingFactory.CreateBlueFallbackRolling.selector); + assertEq(logs[0].topics[1], bytes32(uint256(uint160(caller)))); + assertEq(logs[0].topics[2], midnightId); + assertEq(logs[0].topics[3], blueId); + (uint64 emittedStart, uint64 emittedIncentive, address emittedRolling) = + abi.decode(logs[0].data, (uint64, uint64, address)); + assertEq(emittedStart, start); + assertEq(emittedIncentive, incentive); + assertEq(emittedRolling, rolling); + } + + function testCreateBlueFallbackRollingIsIdempotent( + bytes32 midnightId, + bytes32 blueId, + uint64 start, + uint64 incentive + ) public { + incentive = uint64(bound(incentive, 0, WAD)); + + address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + address rollingAgain = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + + assertEq(rollingAgain, rolling); + assertEq(factory.blueFallbackRollingOf(keccak256(abi.encode(midnightId, blueId, start, incentive))), rolling); + } + + function testCreateBlueFallbackRollingForDifferentConfigs( + bytes32 midnightId, + bytes32 blueId, + uint64 start, + uint64 incentive + ) public { + incentive = uint64(bound(incentive, 0, WAD - 1)); + start = uint64(bound(start, 0, type(uint64).max - 1)); + + address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + address otherStartRolling = factory.createBlueFallbackRolling(midnightId, blueId, start + 1, incentive); + address otherIncentiveRolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive + 1); + + assertTrue(rolling != otherStartRolling); + assertTrue(rolling != otherIncentiveRolling); + assertTrue(otherStartRolling != otherIncentiveRolling); + assertTrue(factory.isBlueFallbackRolling(rolling)); + assertTrue(factory.isBlueFallbackRolling(otherStartRolling)); + assertTrue(factory.isBlueFallbackRolling(otherIncentiveRolling)); + } + + function testCreateBlueFallbackRollingRevertsForTooLargeIncentive( + bytes32 midnightId, + bytes32 blueId, + uint64 start, + uint64 incentive + ) public { + incentive = uint64(bound(incentive, WAD + 1, type(uint64).max)); + + vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); + factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); + } + + function testIsBlueFallbackRollingFalseForUnknownAddress(address account) public view { + assertFalse(factory.isBlueFallbackRolling(account)); + } +} diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index ea0a79604..522a1ab2a 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -15,7 +15,7 @@ contract BlueFallbackRollingTest is BaseTest { uint256 internal constant BLUE_LLTV = 0.86e18; uint64 internal constant INCENTIVE_AT_START = 0.0002e18; - uint64 internal constant INCENTIVE_AT_MATURITY = 0.001e18; + uint64 internal constant INCENTIVE_AT_END = 0.001e18; uint64 internal constant MAX_INCENTIVE = 1e18; uint256 internal constant DEBT = 10_000e18; @@ -26,10 +26,13 @@ contract BlueFallbackRollingTest is BaseTest { MarketParams internal blueMarketParams; uint256 internal blueCollateralIndex; uint64 internal start; + uint64 internal end; function setUp() public override { super.setUp(); start = uint64(vm.getBlockTimestamp()); + // Deliberately different from the Midnight maturity: the auction period is independent of it. + end = start + 12 hours; blue = IMorpho(deployCode("Morpho.sol", abi.encode(address(this)))); blue.enableIrm(address(0)); @@ -87,22 +90,23 @@ contract BlueFallbackRollingTest is BaseTest { toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, + end, INCENTIVE_AT_START, - INCENTIVE_AT_MATURITY, + INCENTIVE_AT_END, true ); } function testAnyoneCanRollBorrowerToBlue() public { uint256 midnightCollateral = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); - vm.warp(midnightMarket.maturity); + vm.warp(end); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); - uint256 incentiveAssets = DEBT * INCENTIVE_AT_MATURITY / WAD; + uint256 incentiveAssets = DEBT * INCENTIVE_AT_END / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), 0); assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); assertEq(blue.position(blueMarketParams.id(), borrower).collateral, midnightCollateral); @@ -115,14 +119,14 @@ contract BlueFallbackRollingTest is BaseTest { uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); uint256 debtAssets = DEBT / 2; uint256 collateralAssets = totalCollateralAssets * debtAssets / DEBT; - vm.warp(midnightMarket.maturity); + vm.warp(end); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, debtAssets + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, debtAssets ); - uint256 incentiveAssets = debtAssets * INCENTIVE_AT_MATURITY / WAD; + uint256 incentiveAssets = debtAssets * INCENTIVE_AT_END / WAD; assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - debtAssets); assertEq( midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), @@ -135,54 +139,44 @@ contract BlueFallbackRollingTest is BaseTest { } function testIncentiveIsTheStartIncentiveBeforeAndAtStart() public view { - assertEq( - fallbackContract.incentive(start + 1, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), - INCENTIVE_AT_START - ); - assertEq( - fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), - INCENTIVE_AT_START - ); + assertEq(fallbackContract.incentive(start + 1, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_START); + assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_START); } - function testIncentiveGrowsLinearlyUntilMaturity(uint256 elapsed) public { - uint256 duration = midnightMarket.maturity - start; - elapsed = bound(elapsed, 0, duration); + function testIncentiveGrowsLinearlyUntilEnd(uint256 elapsed) public { + elapsed = bound(elapsed, 0, end - start); vm.warp(start + elapsed); assertEq( - fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), - expectedIncentive(elapsed) + fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), expectedIncentive(elapsed) ); } function testIncentiveIsFlatWhenBothBoundsAreEqual(uint256 elapsed) public { - elapsed = bound(elapsed, 0, midnightMarket.maturity - start); + elapsed = bound(elapsed, 0, end - start); vm.warp(start + elapsed); - assertEq( - fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_START), - INCENTIVE_AT_START - ); + assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_START), INCENTIVE_AT_START); } - function testIncentiveIsCappedAfterMaturity(uint256 elapsed) public { + function testIncentiveIsCappedAfterEnd(uint256 elapsed) public { elapsed = bound(elapsed, 0, 100 * 365 days); - vm.warp(midnightMarket.maturity + elapsed); + vm.warp(end + elapsed); - assertEq( - fallbackContract.incentive(start, midnightMarket.maturity, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY), - INCENTIVE_AT_MATURITY - ); + assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_END); + } + + function testIncentiveIsTheEndIncentiveWhenTheAuctionIsInstant() public view { + assertEq(fallbackContract.incentive(start, start, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_END); } function testRollPaysTheAuctionedIncentive(uint256 elapsed) public { - elapsed = bound(elapsed, 0, midnightMarket.maturity - start); + elapsed = bound(elapsed, 0, end - start); vm.warp(start + elapsed); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * expectedIncentive(elapsed) / WAD); @@ -190,10 +184,37 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } + /// @dev The auction can be configured to end after the Midnight maturity. + function testRollPaysTheAuctionedIncentiveWhenTheAuctionEndsAfterMaturity() public { + uint64 lateEnd = uint64(midnightMarket.maturity) + 1 days; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + lateEnd, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + true + ); + vm.warp(midnightMarket.maturity); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, lateEnd, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); + + uint256 elapsed = midnightMarket.maturity - start; + uint256 expected = INCENTIVE_AT_START + (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed / (lateEnd - start); + assertLt(expected, INCENTIVE_AT_END); + assertEq(loanToken.balanceOf(keeper), DEBT * expected / WAD); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + function testRollAtStartPaysTheStartIncentive() public { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_START / WAD); @@ -201,9 +222,9 @@ contract BlueFallbackRollingTest is BaseTest { } /// @dev Measures the gas of a full roll: supplyCollateral on Blue, borrow on Blue, repay and - /// withdrawCollateral on Midnight, plus the incentive transfer. Rolls at maturity so the incentive is maximal. + /// withdrawCollateral on Midnight, plus the incentive transfer. Rolls at `end` so the incentive is maximal. function testGasFullRoll() public { - vm.warp(midnightMarket.maturity); + vm.warp(end); // Copy the params to memory beforehand so the gasleft() window only covers the roll itself. Market memory _midnightMarket = midnightMarket; @@ -212,7 +233,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); uint256 gasBefore = gasleft(); fallbackContract.roll( - _midnightMarket, _blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + _midnightMarket, _blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); uint256 gasUsed = gasBefore - gasleft(); @@ -228,15 +249,16 @@ contract BlueFallbackRollingTest is BaseTest { toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, + end, INCENTIVE_AT_START, - INCENTIVE_AT_MATURITY, + INCENTIVE_AT_END, true ); vm.expectRevert(IBlueFallbackRolling.NotStarted.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, futureStart, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, futureStart, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -246,7 +268,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); + } + + function testRollRevertsForUnconfiguredEnd() public { + vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end + 1, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -257,15 +287,16 @@ contract BlueFallbackRollingTest is BaseTest { toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, + end, INCENTIVE_AT_START, - INCENTIVE_AT_MATURITY, + INCENTIVE_AT_END, true ); vm.expectRevert(IBlueFallbackRolling.InconsistentLoanToken.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -275,7 +306,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncorrectActivatedCollateral.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -289,7 +320,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.InconsistentCollateralToken.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -299,26 +330,21 @@ contract BlueFallbackRollingTest is BaseTest { fallbackContract.onMorphoSupplyCollateral( collateralAssets, abi.encode( - midnightMarket, - blueMarketParams, - blueCollateralIndex, - DEBT, - DEBT * INCENTIVE_AT_MATURITY / WAD, - borrower + midnightMarket, blueMarketParams, blueCollateralIndex, DEBT, DEBT * INCENTIVE_AT_END / WAD, borrower ) ); } function testSetConfig() public view { - assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); } function testSetConfigRevertsForTooLargeIncentive() public { - uint64 incentiveAtMaturity = MAX_INCENTIVE + 1; + uint64 incentiveAtEnd = MAX_INCENTIVE + 1; vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, INCENTIVE_AT_START, incentiveAtMaturity, true + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, INCENTIVE_AT_START, incentiveAtEnd, true ); } @@ -328,8 +354,22 @@ contract BlueFallbackRollingTest is BaseTest { toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, - INCENTIVE_AT_MATURITY + 1, - INCENTIVE_AT_MATURITY, + end, + INCENTIVE_AT_END + 1, + INCENTIVE_AT_END, + true + ); + } + + function testSetConfigRevertsForEndBeforeStart() public { + vm.expectRevert(IBlueFallbackRolling.EndBeforeStart.selector); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + start - 1, + INCENTIVE_AT_START, + INCENTIVE_AT_END, true ); } @@ -337,10 +377,10 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, MAX_INCENTIVE, MAX_INCENTIVE, true + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, MAX_INCENTIVE, MAX_INCENTIVE, true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, MAX_INCENTIVE, MAX_INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, end, MAX_INCENTIVE, MAX_INCENTIVE))); } function testSetConfigCanDisable() public { @@ -349,16 +389,17 @@ contract BlueFallbackRollingTest is BaseTest { toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, + end, INCENTIVE_AT_START, - INCENTIVE_AT_MATURITY, + INCENTIVE_AT_END, false ); - assertFalse(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); + assertFalse(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY, DEBT + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT ); } @@ -366,27 +407,27 @@ contract BlueFallbackRollingTest is BaseTest { uint64 otherStart = start + 1; vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, MAX_INCENTIVE, MAX_INCENTIVE, true + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE, true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, INCENTIVE_AT_START, INCENTIVE_AT_MATURITY))); - assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, MAX_INCENTIVE, MAX_INCENTIVE))); + assertTrue(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); + assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE))); } /// @dev The incentive `elapsed` seconds into the auction, interpolated between the two configured bounds. function expectedIncentive(uint256 elapsed) internal view returns (uint256) { - uint256 duration = midnightMarket.maturity - start; - return INCENTIVE_AT_START + (INCENTIVE_AT_MATURITY - INCENTIVE_AT_START) * elapsed / duration; + uint256 duration = end - start; + return INCENTIVE_AT_START + (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed / duration; } - function configId(uint64 _start, uint64 incentiveAtStart, uint64 incentiveAtMaturity) + function configId(uint64 _start, uint64 _end, uint64 incentiveAtStart, uint64 incentiveAtEnd) internal view returns (bytes32) { return keccak256( abi.encode( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, incentiveAtStart, incentiveAtMaturity + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, _end, incentiveAtStart, incentiveAtEnd ) ); } From 059e09fb45361ded780f837f56af6d192517e008 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 7 Aug 2026 09:30:38 +0200 Subject: [PATCH 052/159] test: remove wrong test --- test/BlueFallbackRollingFactoryTest.sol | 126 ------------------------ 1 file changed, 126 deletions(-) delete mode 100644 test/BlueFallbackRollingFactoryTest.sol diff --git a/test/BlueFallbackRollingFactoryTest.sol b/test/BlueFallbackRollingFactoryTest.sol deleted file mode 100644 index 3f96e859f..000000000 --- a/test/BlueFallbackRollingFactoryTest.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -// Copyright (c) 2026 Morpho Association -pragma solidity ^0.8.0; - -import {Test} from "../lib/forge-std/src/Test.sol"; -import {Vm} from "../lib/forge-std/src/Vm.sol"; -import {WAD} from "../src/libraries/ConstantsLib.sol"; -import {BlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol"; -import {BlueFallbackRollingFactory} from "../src/periphery/blue-fallback-rolling/BlueFallbackRollingFactory.sol"; -import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol"; -import {IBlueFallbackRollingFactory} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRollingFactory.sol"; - -contract BlueFallbackRollingFactoryTest is Test { - address internal midnight = makeAddr("midnight"); - address internal blue = makeAddr("blue"); - address internal caller = makeAddr("caller"); - BlueFallbackRollingFactory internal factory; - - function setUp() public { - factory = new BlueFallbackRollingFactory(midnight, blue); - } - - function testConstructor() public view { - assertEq(factory.MIDNIGHT(), midnight); - assertEq(factory.BLUE(), blue); - } - - function testCreateBlueFallbackRolling(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive) public { - incentive = uint64(bound(incentive, 0, WAD)); - - vm.prank(caller); - address rollingAddress = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - BlueFallbackRolling rolling = BlueFallbackRolling(rollingAddress); - bytes32 configId = keccak256(abi.encode(midnightId, blueId, start, incentive)); - bytes32 initCodeHash = keccak256( - abi.encodePacked( - type(BlueFallbackRolling).creationCode, abi.encode(midnight, blue, midnightId, blueId, start, incentive) - ) - ); - - assertEq(rollingAddress, vm.computeCreate2Address(configId, initCodeHash, address(factory))); - assertEq(factory.blueFallbackRollingOf(configId), rollingAddress); - assertTrue(factory.isBlueFallbackRolling(rollingAddress)); - assertEq(rolling.MIDNIGHT(), midnight); - assertEq(rolling.BLUE(), blue); - assertEq(rolling.MIDNIGHT_ID(), midnightId); - assertEq(rolling.BLUE_ID(), blueId); - assertEq(rolling.START(), start); - assertEq(rolling.INCENTIVE(), incentive); - } - - function testCreateBlueFallbackRollingEmitsEvent(bytes32 midnightId, bytes32 blueId, uint64 start, uint64 incentive) - public - { - incentive = uint64(bound(incentive, 0, WAD)); - - vm.recordLogs(); - vm.prank(caller); - address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - assertEq(logs.length, 1); - assertEq(logs[0].emitter, address(factory)); - assertEq(logs[0].topics[0], IBlueFallbackRollingFactory.CreateBlueFallbackRolling.selector); - assertEq(logs[0].topics[1], bytes32(uint256(uint160(caller)))); - assertEq(logs[0].topics[2], midnightId); - assertEq(logs[0].topics[3], blueId); - (uint64 emittedStart, uint64 emittedIncentive, address emittedRolling) = - abi.decode(logs[0].data, (uint64, uint64, address)); - assertEq(emittedStart, start); - assertEq(emittedIncentive, incentive); - assertEq(emittedRolling, rolling); - } - - function testCreateBlueFallbackRollingIsIdempotent( - bytes32 midnightId, - bytes32 blueId, - uint64 start, - uint64 incentive - ) public { - incentive = uint64(bound(incentive, 0, WAD)); - - address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - address rollingAgain = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - - assertEq(rollingAgain, rolling); - assertEq(factory.blueFallbackRollingOf(keccak256(abi.encode(midnightId, blueId, start, incentive))), rolling); - } - - function testCreateBlueFallbackRollingForDifferentConfigs( - bytes32 midnightId, - bytes32 blueId, - uint64 start, - uint64 incentive - ) public { - incentive = uint64(bound(incentive, 0, WAD - 1)); - start = uint64(bound(start, 0, type(uint64).max - 1)); - - address rolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - address otherStartRolling = factory.createBlueFallbackRolling(midnightId, blueId, start + 1, incentive); - address otherIncentiveRolling = factory.createBlueFallbackRolling(midnightId, blueId, start, incentive + 1); - - assertTrue(rolling != otherStartRolling); - assertTrue(rolling != otherIncentiveRolling); - assertTrue(otherStartRolling != otherIncentiveRolling); - assertTrue(factory.isBlueFallbackRolling(rolling)); - assertTrue(factory.isBlueFallbackRolling(otherStartRolling)); - assertTrue(factory.isBlueFallbackRolling(otherIncentiveRolling)); - } - - function testCreateBlueFallbackRollingRevertsForTooLargeIncentive( - bytes32 midnightId, - bytes32 blueId, - uint64 start, - uint64 incentive - ) public { - incentive = uint64(bound(incentive, WAD + 1, type(uint64).max)); - - vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); - factory.createBlueFallbackRolling(midnightId, blueId, start, incentive); - } - - function testIsBlueFallbackRollingFalseForUnknownAddress(address account) public view { - assertFalse(factory.isBlueFallbackRolling(account)); - } -} From dff0e873ce8440f48c1f277a1bf152748ee76e74 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 7 Aug 2026 15:09:09 +0200 Subject: [PATCH 053/159] refactor: error name --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 1 + src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol | 1 + 2 files changed, 2 insertions(+) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index b4bb63435..6094f2afa 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -93,6 +93,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { blueMarketParams.collateralToken == midnightMarket.collateralParams[collateralIndex].token, InconsistentCollateralToken() ); + require(midnightMarket.collateralParams[collateralIndex].lltv <= blueMarketParams.lltv, BlueLltvTooLow()); // Round in favor of the Midnight position. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index 12f55b042..d886c8d87 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -8,6 +8,7 @@ import {Market} from "../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// + error BlueLltvTooLow(); error EndBeforeStart(); error IncentiveNotIncreasing(); error IncentiveTooHigh(); From 9b4a0cb9f7caab54dcb5767222ec79df02c7ee96 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 7 Aug 2026 15:32:11 +0200 Subject: [PATCH 054/159] fix: require end time --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 1 + .../blue-fallback-rolling/IBlueFallbackRolling.sol | 1 + test/BlueFallbackRollingTest.sol | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 6094f2afa..7eb660297 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -86,6 +86,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { ); require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); require(block.timestamp >= start, NotStarted()); + require(block.timestamp <= end, Ended()); uint128 collateralBitmap = IMidnight(MIDNIGHT).collateralBitmap(midnightId, user); require(UtilsLib.countBits(collateralBitmap) == 1, IncorrectActivatedCollateral()); uint256 collateralIndex = UtilsLib.msb(collateralBitmap); diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index d886c8d87..20fce8b7f 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -10,6 +10,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// error BlueLltvTooLow(); error EndBeforeStart(); + error Ended(); error IncentiveNotIncreasing(); error IncentiveTooHigh(); error IncorrectActivatedCollateral(); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 522a1ab2a..afcdadd11 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -262,6 +262,17 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testCannotRollAfterEnd(uint256 elapsed) public { + elapsed = bound(elapsed, 1, 365 days); + vm.warp(end + elapsed); + + vm.expectRevert(IBlueFallbackRolling.Ended.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); + } + function testRollRevertsForUnconfiguredBlueMarket() public { blueMarketParams.oracle = makeAddr("otherOracle"); From fed651959a5b1565666329efd1637dc433a5f4a6 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 7 Aug 2026 18:11:45 +0200 Subject: [PATCH 055/159] refactor: inline incentive() --- .../BlueFallbackRolling.sol | 26 ++------ .../IBlueFallbackRolling.sol | 6 +- test/BlueFallbackRollingTest.sol | 60 ++++++++++++------- 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 7eb660297..1a6cabd2a 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -41,7 +41,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint64 incentiveAtEnd, bool enabled ) external override { - require(start <= end, EndBeforeStart()); + require(start < end, EndNotAfterStart()); require(incentiveAtStart <= incentiveAtEnd, IncentiveNotIncreasing()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); @@ -51,23 +51,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { emit SetConfig(msg.sender, midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, enabled); } - /// @notice The caller incentive at the current timestamp, as a WAD-scaled percentage of the debt rolled. - /// @dev The incentive is auctioned off: it grows linearly from `incentiveAtStart` at `start` to `incentiveAtEnd` at - /// `end`, and stays at `incentiveAtEnd` afterwards. - function incentive(uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd) - public - view - override - returns (uint256) - { - if (block.timestamp >= end) return incentiveAtEnd; - if (block.timestamp <= start) return incentiveAtStart; - // Round in favor of the borrower. - return - incentiveAtStart - + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); - } - function roll( Market memory midnightMarket, MarketParams memory blueMarketParams, @@ -99,9 +82,10 @@ contract BlueFallbackRolling is IBlueFallbackRolling { // Round in favor of the Midnight position. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); - // Round in favor of the borrower. - uint256 incentiveAssets = - UtilsLib.mulDivDown(assets, incentive(start, end, incentiveAtStart, incentiveAtEnd), WAD); + // The incentive grows linearly from `incentiveAtStart` at `start` to `incentiveAtEnd` at `end`. + uint256 incentiveFactor = incentiveAtStart + + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); + uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index 20fce8b7f..3756953b4 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -9,8 +9,8 @@ import {Market} from "../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// error BlueLltvTooLow(); - error EndBeforeStart(); error Ended(); + error EndNotAfterStart(); error IncentiveNotIncreasing(); error IncentiveTooHigh(); error IncorrectActivatedCollateral(); @@ -66,8 +66,4 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { uint64 incentiveAtEnd, uint256 assets ) external; - function incentive(uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd) - external - view - returns (uint256); } diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index afcdadd11..89bc2d757 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -138,36 +138,39 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(loanToken.balanceOf(address(fallbackContract)), 0); } - function testIncentiveIsTheStartIncentiveBeforeAndAtStart() public view { - assertEq(fallbackContract.incentive(start + 1, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_START); - assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_START); - } - - function testIncentiveGrowsLinearlyUntilEnd(uint256 elapsed) public { + function testRollPaysTheFlatIncentiveWhenBothBoundsAreEqual(uint256 elapsed) public { elapsed = bound(elapsed, 0, end - start); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_START, + true + ); vm.warp(start + elapsed); - assertEq( - fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), expectedIncentive(elapsed) + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_START, DEBT ); - } - function testIncentiveIsFlatWhenBothBoundsAreEqual(uint256 elapsed) public { - elapsed = bound(elapsed, 0, end - start); - vm.warp(start + elapsed); - - assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_START), INCENTIVE_AT_START); + assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_START / WAD); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } - function testIncentiveIsCappedAfterEnd(uint256 elapsed) public { - elapsed = bound(elapsed, 0, 100 * 365 days); - vm.warp(end + elapsed); + function testRollAtEndPaysTheEndIncentive() public { + vm.warp(end); - assertEq(fallbackContract.incentive(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_END); - } + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); - function testIncentiveIsTheEndIncentiveWhenTheAuctionIsInstant() public view { - assertEq(fallbackContract.incentive(start, start, INCENTIVE_AT_START, INCENTIVE_AT_END), INCENTIVE_AT_END); + assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_END / WAD); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } function testRollPaysTheAuctionedIncentive(uint256 elapsed) public { @@ -373,7 +376,7 @@ contract BlueFallbackRollingTest is BaseTest { } function testSetConfigRevertsForEndBeforeStart() public { - vm.expectRevert(IBlueFallbackRolling.EndBeforeStart.selector); + vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( toId(midnightMarket), Id.unwrap(blueMarketParams.id()), @@ -385,6 +388,19 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigRevertsForEndAtStart() public { + vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + start, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + true + ); + } + function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( From 01a91b3e50b9440e2284bd798217c774f4f5fac9 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 15:06:46 +0200 Subject: [PATCH 056/159] test: lltv test --- test/BlueFallbackRollingTest.sol | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 89bc2d757..e0ad3b938 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -338,6 +338,31 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testRollRevertsWhenBlueLltvIsLowerThanMidnightLltv() public { + uint256 lowLltv = LLTV - 1; + blue.enableLltv(lowLltv); + MarketParams memory lowBlueMarketParams = blueMarketParams; + lowBlueMarketParams.lltv = lowLltv; + blue.createMarket(lowBlueMarketParams); + + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(lowBlueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + true + ); + + vm.expectRevert(IBlueFallbackRolling.BlueLltvTooLow.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, lowBlueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); + } + function testSupplyCollateralCallbackRevertsIfCallerIsNotBlue() public { uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); vm.expectRevert(IBlueFallbackRolling.NotBlue.selector); From eb46443e92beef0b3f1a48154b3b030db2d0b976 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 15:17:21 +0200 Subject: [PATCH 057/159] fix: remove increasing incentive requirement --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 1 - .../blue-fallback-rolling/IBlueFallbackRolling.sol | 1 - test/BlueFallbackRollingTest.sol | 13 ------------- 3 files changed, 15 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 1a6cabd2a..2236b61bc 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -42,7 +42,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { bool enabled ) external override { require(start < end, EndNotAfterStart()); - require(incentiveAtStart <= incentiveAtEnd, IncentiveNotIncreasing()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))] = diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol index 3756953b4..af2b9ed48 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol @@ -11,7 +11,6 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { error BlueLltvTooLow(); error Ended(); error EndNotAfterStart(); - error IncentiveNotIncreasing(); error IncentiveTooHigh(); error IncorrectActivatedCollateral(); error InconsistentCollateralToken(); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index e0ad3b938..0edadd77c 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -387,19 +387,6 @@ contract BlueFallbackRollingTest is BaseTest { ); } - function testSetConfigRevertsForDecreasingIncentive() public { - vm.expectRevert(IBlueFallbackRolling.IncentiveNotIncreasing.selector); - fallbackContract.setConfig( - toId(midnightMarket), - Id.unwrap(blueMarketParams.id()), - start, - end, - INCENTIVE_AT_END + 1, - INCENTIVE_AT_END, - true - ); - } - function testSetConfigRevertsForEndBeforeStart() public { vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( From bf81ea9791be61f2ffc028f68bfcd8ff2eca58ae Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 15:17:47 +0200 Subject: [PATCH 058/159] doc --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 2236b61bc..83726175f 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -29,8 +29,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { /// @param start The start time of the rolling period. /// @param end The end time of the rolling period. - /// @param incentiveAtStart The caller incentive at `start`, as a WAD-scaled percentage of the debt rolled. - /// @param incentiveAtEnd The caller incentive at `end`, as a WAD-scaled percentage of the debt rolled. The /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. function setConfig( bytes32 midnightId, From 098e1e34d06be93f681cafb81fd8bdd6a286a945 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 16:16:10 +0200 Subject: [PATCH 059/159] fix: incentive at start max value check --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 1 + test/BlueFallbackRollingTest.sol | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 83726175f..3e2da7f06 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -40,6 +40,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { bool enabled ) external override { require(start < end, EndNotAfterStart()); + require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))] = diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 0edadd77c..f032b66c9 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -378,7 +378,7 @@ contract BlueFallbackRollingTest is BaseTest { assertTrue(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); } - function testSetConfigRevertsForTooLargeIncentive() public { + function testSetConfigRevertsForTooLargeIncentiveAtEnd() public { uint64 incentiveAtEnd = MAX_INCENTIVE + 1; vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); @@ -387,6 +387,15 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigRevertsForTooLargeIncentiveAtStart() public { + uint64 incentiveAtStart = MAX_INCENTIVE + 1; + + vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, incentiveAtStart, MAX_INCENTIVE, true + ); + } + function testSetConfigRevertsForEndBeforeStart() public { vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( From 1a1f195551d4b1e1680819784b6e97e4bd7b2ba6 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 16:57:20 +0200 Subject: [PATCH 060/159] doc --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 3e2da7f06..fac857e86 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -80,7 +80,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { // Round in favor of the Midnight position. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); - // The incentive grows linearly from `incentiveAtStart` at `start` to `incentiveAtEnd` at `end`. + // Round against the keeper. uint256 incentiveFactor = incentiveAtStart + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); From b5aa3201f87786152e31689a9814023ec84bcf6c Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 10 Aug 2026 17:44:51 +0200 Subject: [PATCH 061/159] doc --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index fac857e86..d22e9173f 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -27,8 +27,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } - /// @param start The start time of the rolling period. - /// @param end The end time of the rolling period. /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. function setConfig( bytes32 midnightId, From ffb0dca6d5f5c945de8c7944f901c728a8849c34 Mon Sep 17 00:00:00 2001 From: PA <50184410+peyha@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:53:01 +0200 Subject: [PATCH 062/159] Update src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: PA <50184410+peyha@users.noreply.github.com> --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index d22e9173f..264779548 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -78,7 +78,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { // Round in favor of the Midnight position. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); - // Round against the keeper. + // Round against the roller. uint256 incentiveFactor = incentiveAtStart + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); From a729282936300583c00e343fd322cb5d6fba5c7d Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:24:35 +0200 Subject: [PATCH 063/159] Add files via upload Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- .../2026-05-29-midnight-core-competition.pdf | Bin 0 -> 958486 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/2026-05-29-midnight-core-competition.pdf diff --git a/audits/2026-05-29-midnight-core-competition.pdf b/audits/2026-05-29-midnight-core-competition.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b0ad4ce7a392749c2a66d005b2d44fa778378e0b GIT binary patch literal 958486 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�>rJ8DZ`P89bHrrPustE` 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 z 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

t}#tZ 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%0A}WuRYvS`UtMn*vNsZ(9m?uv%0^!v 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 |Aw8Rn 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

    ~J3Bue-;yPEHV{*3PFW9icC;@9fq zDYrxU#1r=~cI!B_rPi7zH@K#qRD0Mvc%;`7S+(Z&lvWWGO5u?xaT}!$S%lFm!^~$_ z=P=zh)FWa;|H$%ta*4T(*hezIM?S>gbUK|S{P74<;R=|}tSNQ9W6zWrk!#Xm z4@s~B#R-WSiysc9q4Uhevp?^vZ5eLcs z%1R!CLFl2h1N)dFEeIB*3hLBlt^b>ToeRQTuRIyvynLyJcwb};?$%obup_j2A5_?L zm2Y~t|2Kxsz?qwSc?3@pp5q&q13LU?p%*7NB*Uwr7U*OL@`)aQ4sh98Yjfc{$}c}-!IEC)Fq zk7`Y9JoD5YSE=8)LRApfvbY1B${l74zu=Sly!Lkw8&Ia`Od>&eI$@G^paUz2$So#f zAG&|U@z@Y!TU`G&2zF&KO}lBG#AyE)qKI3ASxvMVQ}|<0m@~F*QQhKnN#ucbKTejc ztM2T9e#QzsIyy8}4LC?;0Q=nf_(VL#oQ@{@@**2iVNFM z&`=n&ZLc_k88}>3!iQl_o~!v~QRn=wnRMUd{+GV-jNb7TXkCsocd9uS6dJpecE_zY zn{OH((XbX9Z+j@SA7gfAN)x-y4jVU{pLCAqpOa5(Qm$s@TXNSLu9fVI>8GFcuWo4l zPYmNXT=h@-4$$01FvmSSHR#x0`y_n;x*ly!ANid-AmTR$1F59plodyDDuzwdW_$fFEnkTiuaQCLyI83YZrWO4qWH6A9s?y4tWl)i++sF zgCDlmw9G&;v!S+Z+-!%3*sQ+o6kdz71_RG;!hQrv7Lf#2$xO5TvuItHIgFSZ8tDAh zO6-@n%sMC4T|>@WNFrBAWMMMrjU25Ijw*$0nu@H2)^~$E(k{S?;EyOv+q7@x-z;Nq#UxK* zlni4mcn2@HARsRnIjRWLs6hERS!n7HpRd}RiJ)xY4L>IIWGitxte%*?3CTqMS9D1fYoHTbQK) z>64IFBPh28BUbaR^dSPqkJitYZGhFvecp1Jz6bD4JMH|c&R2I8nT(QFLCG2 z$=wp(@Bmf$w;-G7g(|GuoV$d5<&$nc;8!~N_vJVwH7_4O@RVyY!7;J(${}+D@PL`M5U_cewd7$ouAaSFJuC;`aQx0!tc+&UNV7Y1{ z2@x(7PcA|D{21bal3EyyAu)6J3O>|Ffl zo>8(Dm|3B=*rDesHtcQi2M;G_qQdNb^_)_SL_L{zIvy+;)F9@ zW~sGO3vd0HwuD!5_(ggzv))6#H23gw*gEFps}dnyDPz*4;&x{1UVG-cnX7g4CF zTjwg;>h^n(SP`R{Xb~_|3AgS`C4RWuYiG%IS&XdY~S52qx+xK z^RSE#gQEgQPQOZY0 z0q3(7STqux7Csfh%ZOt7{u;G+qRZUkoP3lNkC5!4mTF@Zi(*Ny2m5!g##*`k+;FN04A`q&>P>8}_4twE zpwyI?mMvQeC}MX>&&^Yb$O{k&~?)AXD%!(;jjn9o!V z7WO=>pfzalEHQRsnt8r7NqNIkwCait7^n*fprWKQmHYm=zKaW#lL@rhB3=16H59MI z0GMGI#`~US?KUk)(3o3#d2gZO;)E1%I9#todV!++$N1T&czFxR2dlezou?K(q+hds z*{Gu7atWl@63EGfGS<3m4bUy_}2NMYf8rm0T-jD`YEYDn6D{msFQl7FVRd zO9&Dzm@q_QI#7n@L)3>I&k86(k9Lv-hUl7>pltDoq&pyl zZO{W+({|WMin%8I2c_ij?;x zr$nN4UOhxPK0!dDOCev8`fT+{(azUAw7Pxl;LBQR$5B zTJAYC(tQDKa0u9Z&w?E(g)DVBB*OY1hr^h+)@xaH&1Ko)YG`WKMkM1U{7G=Hu04lj zEPuw>`r%s5xOqdUaow_@N&cyTqo}?GXzE&TXf>Wd1^(K1Yl8vdTyImKn{7VUsSU z&9eA#Xpf9eX_sEGg*c<#1_y4k{z!{iAWMk8x$1Y{1)0 zwkeIr?a5WW$I=+!}%Rcb*{jNl^xrBPSVfS@7+hW9%Y~C+PzEI z&)a9h{SnH9&Bc@%a~rUGc->*diT8Ohx%Fee;G(%bbtCWN!3cz;M}5$TIN~EQ>BC5a zDLhuegg&%GFxl4|KY+pj8Puac;bV^pwi*lOq))|>3%JLK^k#s2pa&w;L&-SP#u;g( z$09QTgzGnF!yTP>jtWv}G9<}3_m&zWmI?`{hb5*_j zRPNcB`HAXNSp|;jac=BEx}m-FJKp`%1H(yZ{gATmZr;IlLHmXd+JW%+%kDF=(Yj8r z+M&(#^X{3pLH!2k?y0`PGUbDE8lpcXn1LC%UV$y&;Y|g+=A*&!<9Y!+-w|$s;ty)Q zL7eo=V9`RfRm( z!S(nz+X1e~F?IQK>vL-jt)6jtL1XW6dIk3QN83T-h2ZNmeF4Pw$-dz=51_TdsO~vm z0mcsgZTGY7gL8Lv@dtJhq{=y@erqf`P87RCVf+H!-ZN+3Gwy+YDFEjR%(>(881#7x zMxTeE%g67E(%wgX3jK}0;`Zaeqx_-+8??lLipB`YHsiuO%{kkXZiB%u;N9o{!q)D0 zy+d#v;ZU%H&mJQBM++P%yJfE))^>sU9yYs0ukNdG_)X&kzAo@pky7RCvt`NFyTKRl ziFDxOmps2Qdk53auev35?o+hvx#I=x{!_aKt0wy658t}O{7ktXGQf@aIso|$5FQQE z-SKs#T99W$v*AbDbKT}`YYEUj9=egq^oy%Skg%oi43#TQNS>op=7BP&@*Hq|WRWhg zWeC5@aVsZk-z<3K3@&R0OPVqA@Hw|7ob01*gvHK*X-P-gb9TpYo(Xzo@${LVq4bEO z>mz%`+RiI`W!CI}K45-w65*ZDzWp6NRKE$8#_=y@$DzB^TMGq%#X6U zbMpZ=os)cmncY*+7|nU$mK;w1LVG<9b%X2{^K|FfG_T$&4$l&(os(S}IA_kqIs-DD zFZ%UszAjc6ywj=)T6O{93HK$6^XSXiA){DEH z2S)nl*@M=f6Kw)!bu>!QHE38)LO?k~-?Is)Cn25`DH=9%NsZ1!>4(;+1H6$3`j@&* zMh2--=Z~gtS(eAg-{E?3MC-ZM-BwV50UljjhH=XlAdgvIju}H|#D!$Q7%VmmCGWjt zXX&J5!GCr4*7k)#LOV2C`S``i`CONpyskO3F)3oQ9%iMk-hviNW2vns7FH1w6vSOn z=IyoRJ&2+xXQk3cQphSwTBg0V-GL?eGboyHbPHvcu_eAU2iuon^xQ~njuyF- zLSCs>m2MQC$qX5&YQ57{q4ySaZ~!@2x))7hxk9Vi+2M2$1WuM>w%ePuGN~jKN+9v7 zWt1?9l`4XTKWGP{gi z;UV(XW z6ABvbdV}$JLP!XSFbT=Oa6OqP^x@aWPKK@rcdFDYwr)B3mf=21HI zKt`$$c=Fco6%Ak;`oL9rZ*c99~0d4};SpC$qz3vaWz5-zMN%8Grs7zMTrYL>DCf%OQ3*&4rfKNMhHa_>NdlZw=Vtn{XhdEuv8LLrQ?$o*bGdD zGFuZFH4iDFmnNrw%U+A;ySTV6F3o^)S21*1!>zk0|KWScV)y-hhVp!IdyCq+nVcT` zV3y4yVrepW&LSVPBn|MVE%>Il?>F{f9~qM3Vj9n^_7rjt(LHDS-6?DBS(|JF@uVfe zlJ)on>4pwnneDxPXLj~u%$#Ez3k_ZIy)(`aBV*4LPvfM|qFIV3+N|t&HWr4tq$-hP zQV-G-VK|v96I@H@p4f~ky?E4u;eVbl{{AH{6jlq{f%StH*1(nyjwU6XDT?!bP5<&& zdBhE4^KtwI$&%YB&bxCZMD^l8au#fj9zd2ow3)z zBs+D`@QtTiCxLKs7ie%YRz5IL)IVWv1Pkf!yxK-1pRW&)^8#>Qqpr_UO zB3^%+O0Eg?Cjgmrqb}8?|7^gL=F=cSyBUntLw6oUO?5;*I#xD~&i4N%5M~ZnHFh{{+uE1SMRz=1cR$rDz{B zPExb@7Uc_sEaqf<1FoAKU*M-qq)_0RHqO1wF(k9%^|!FGO==bU4#BCkJWh}j#F2go z3PvH_Ot$(fdv|fiMPS!nbs}M{Onl!Un0{4; z)XVNrqqE0R{>nVz(Z9lE>NbFpIfqsCLVG+$t6H+*@Vk} zx;v0xdlj`TYuT}U*7PkTSY3(B+^KAn$>K7u*=duAD`C7u?>ecmC^%^0(0H_~9(XxS zcHw)TzbPy2tX`O%R-w9%1>bo!z4WbIDr%IXHwmIj!^N>srf~0C)PXsxS%~QZE zlS6pP`0bQ(xBN$?aI;k4>Gn(eJmOp{+#yr;@Tc&!d91}8f#{UeVh(z*cCF*feemKJ zm=>rS=YN`(+5bPMW#<3eQY(?)_JAHC`1S|&1~43Nfen&)6H3@3U;P;1nx*Uj>&jn4 z@@h;R?(1^{PoQ|&g%t@A|8eKd-HMd8R{4(n2`}I%W}fxzNskR=(s?^!+^G0{&hLU1 z0BA_<8t<%fzAGR{CiS>NsiC*|K;eFoKu_sg`w2v}yocBZmt%W?_N{pnP zP7%^cLi)`%oEVBCp}Q~P?@4raI+N;YO=yV{xHK9xR?oV@YG&iCkK_P4QJ|OH4XpGEh2iaIL%mw5H_#%>p?$R*A>bO5e zrbQU#d=gyKmen5|mBLipC)$g~Wij2N1{*P&EzK zuJ8jGv*Q9l{3FMCiv9uti4wZUBb4T1y!({!<2NELi2$Bl!GsjVf$)AR1`+hFoH@Sk zeR6Awl25^2Jf|8#`){oM1nED*%$NcMw{ZbiQvAH|S3>;Eulvgb=;xgY^2_T3tbqc! zw6>gns`Kpv!~GZ^{g#Uu-rWZb?g3~r!_>hKp+)@=-U$R~^#h%d84cnIhHUR!|tI2QixXNfbN`L$LS z^q-Ub1Kuo%oE@qghED!eiWi_1(iUiqCn&e_;+t?@Yo2Gx#-F!0N>6-rIvf}S1oS%@ zvcqjD`g9y1GA!nI3J)4b!fClJ?01*ccn1N&_jxtx@#_RlRG5>)H1D<{&ssCu;O5o;drBk;SFkqsq1W zx9sL8X>UYCzUb>t-mX%`)6`hL1dJp*ZGUyPql~l?@Y{J`u!7fthjSF9MkGDB)U24P zQnDo%ai~){j`|fIZYuF*&Q%zU%fY+nCz}LBxPq90uaw-WbHMHg_1;(}|5An{JvAAs z{VGPKPh8@|{;8f6aQfQO>r#8p*sp!rf>Rn05W=AAwTFZr;NJX&M zX#jGejuW=v!=?U;sr#^SPR}`ZJ^W_=c+&KO!lDHKBVeul?_qI`aQb-twITLfMeHzzXbJ-30)1`tSXXrMybw{AMudL_V35PQuzY{Rj);utZ`YvE757bHVTIr}~DgxgsK z*S}(8>Tqmc#Z+p%%R}M}d&@J=5e@FqQc+GM7!Ow8fhGqTEmzu}_;?TOFX*m0if1q& zHp8Pr%@Z{EEXP6)QL6JYUPKl&2~d59sGg4`j;C^SF)1emiV9kY$v>wU>;hmT4QOO9uChOm>{ zh<$2VM%>QqEkyZpEM%)!5xyc|M`uG}e5RRNtT~@i06Nkd2+oR~ksg@0IM#wL@Tgtq zG=&0vWb}U<5pBv~2!p&jr)#?65gMq&fh}hr!${;RfpQ{<=Gn_UNFcl!%SAjUM9RZ_h7_ zRzFnrpPqvMe$|%apKLkh$u`0+497_(ELijCI2;kjdmSfcif;yj6W@^4R0YZuSK|yf zfN97GOzkcrD|mO1q}m~88%$a8C#ovuq1$(SweE3SSA-H5jT7GTxhQ%2=%iLVoeOCL zx5NgiXTbFCpx%@x3j`+%fRLC|1|NH68J`cNqs91uj}5C6NuOM*Ze^i{fPgEe+tt1p z6e)gSKOe*1h0XRn`kdwROFV2S!i<{p*ZEZaG=;o`;6g+xov_HmjboO_d_Lgqu4hpy ztQkVmZ{;&%%nd0Fu>Sf6MvrKA5dfL0Cd^AV%n!sa=l*yNYeG|vZHM|S&C;&8U{c;O z3C)!n*dDtyV|IN2X=lIm_@fo zZ>lCwU%%?kL3weekxy*#5#EaPfbH3U1G(B%78^Vl=>&RkqY_*oRRB(7NG8M`gcJ?MDc%ER|8mHi%RSz`>8O1>*?KU=wCDLKseSa#^QlWIQ0vgP$tmXom$lNxF7w}Ob0Whrsa&TEyaaV(p{ zXk9tdu4f@h6I?DXLcuoEzwvP>%`P4wY46_6!YLDqIg4CEZV_^oExHX-f#U>`eYnQq zfxCam#p_K;1&hyfj;Jr%P^(0yz+qF{REw_wr5nPXhbo(K;$y7GUw*GfT2teD*OMaf z9+Go%Pi$oSFjM7(#9+P~npo#t@QfdjwFn0v)zOI3D$Gix{xaJA+L(@&M3e#+N`zHw z-eU3>iJ1Be!pbQDzr22lmCQ90rp~vZz-h&KotSsr(?|mK){;{=fMg_F>yN_Ydk^TZ z`%YUewqKp`DQq?#YYdEUloSEpet*)I&}~8}^5>&+w5Bw^98G(ankQJjQKv5JJ!iRO zmhmVX1)ae&#gM^iQU*PARMWMaNn&Y7!Hr6VO+RZ{7=J|@%#@o+&bz9u_}j<`W8yg8HgE|3t8?5 z>uvgKo7&DCl%_6+>Fy9gM1L@$j1ZAw%+W60F=;osO!IQhWaDL^9Q8!rg8(Rc0Z8I! zA-OMS8E)tl8kKWwL=5(63=7Vr!Y4Ewb=d_tQtCcpi6M_NPEfFw0o`4ysxc9s&}XQ` zr%p@qp4&Ld=(5+&i)9b#UwL%+Jj8dJ#gs}&?JxZ&X_N<< zS1C)Uy;Db>p+7n#XoLO<=h%2v3zZ?YqC=Vf!hku}lZMow55qxNX`B}vRFV(jX%c@*OG1WBE z>)zurpj4sgG#4<(Gx5+3k!bG@zE)DMJmz?}#Dj+>^Pq>Evg8>C$-=H8gWjP%slM=J zLw|E*<2sR?Qy#O}KN7;N7i&oRyHZXhgE_Hum*8|QxMkW`#j5ijGS+zcFAZgmBXdY> zA^kqCwGk6!+KUszeIzHFUBK;m1g1VQWGxK7Y-?b38Xa;X=Q6xG%2IdL#M7b^akg}P zafX3L9mpSVuQnYnML-?-BhUzs-(w@l8n9`}0Ib14y9IaSGfAh_;re-MA*OZ;lu%o2 zZ((y7itZ7~YpQ@X!0x*V_HvX9n5z`VQ&F3)H}Pw_b{{;7)l@?`vVnAug6q*0W?-ds*U9-V^me5T}JlQI(pOS!W1Jk7PLc+*y;h)w{g>J zP!@*1hg*8oqVAgB*ghE>MswfrDW?Ox_2B(2Gpo`|SE4f5BNLNmdeHk5JT3wDpmF=zH z_JiSUsr5fyDXc>^u7w?_k~(pm8iTbk6K~6oji02842U+SPA+zNd|e;k1<+v{ouYNk zMb@@LC%wMu<#poCIm_uC;9D=Il@bwW7`TiM`Ve20_s0CRXo(;{quNifo|(_Jy^taf z-`7e3jSCYu#Fb^B@p(MN=5f)upHWmIpz>af+I@J8zO512j>^yhW6cvkW6X8K_>jO_ zgVhhXJaX->G1fPjs|t*G`&%d+>F6=yM0>PkEYp*kDXGxLlc1Oqm&E|iOVch3AbNM6 zugcy6LmDrK`2GZmnkSiXvjMIY*gm`G3%XSoEE6`vwTmAiITmR@ONR7f2x4AhVe&qU&>%w9!wR^!sOu$h2Tx;-ZB z$%HCdsX0mjHvjbmhW0Z2?OzHOaD+;G-i$2jSqTosHbuf(gBu?$3b$H>G0#}ee)=fr z@N@`^J?DcK0 zl0Ya9`KTI$?scgn*``?-UKbUw^^lkL>aA9(3oWFqCO)`NRDJ96fyL|_7E6{bSi94p zcKLog2gQUsYRU?n_=jh90*r}d^|OZJAeI*)nc%^*UDwmmZ>VI}y+fPAxb*H@So=+zk3LNF|8w!?w^uK$s2xBBAb6Pf=)pS`f7pUAo-#)@=ATXIwJ89%uV! zzE^NKp?{qK$<>KRFSgBd2qkP5f;M>#=g$j1)5S4O!#%frI~ZkgP1K&@5#7W??J~Mh zrywN}Or&<$K?pXL1k$8f$)4`jL$gi0dm5c|y73GVs8*J1t#N}pFKXFpF21B2F77!i zBsUr4`II}hV%f8WZGaJG>$bgV`>4r!x8$^rcm;1AeN`XV4i4a4?Cn$gVprwM*MVk8 zACU8VASY=4n)&Kxcgb5a1xVuk%4`i+28UyEii{bK$m7TzU&cJ z%X5RRJ8g^&r)PUh_t}bo{RzykSSxA2oKz)NNjO=H69eBIJY9l z+`5ERzu~TYQc{_H*%hW0n{I}@CNDCd!d!2KZbw{YGqk+8TW#?wzWz2Dz5O~@G{GUP zx|%mz`Q1TzfY*)0kqJrg63`!)B}Vt$Ka1nVQQCc8`9#vtQklg)=@3=V5hP? z@BDAf9L~9E2YBVjhPvI@A{5WT*qFtQu+AG%FfCX$fp=U%n2`WHk>^e*xt}Onb-0G7 zjp6;13aNZq95PaqS|EGV;W+y00sdyXzI4* zE={O9Z)Lj=pPfR6aN4ik!*A7URd}vm`|>;Lp9SD<(-9R*o9s+|fKrznyEUW}qM$;R zgwdXWpa-;TN#4LOco)#ks}o2Gq^#`tfpp%T-LH~ZDR*RIG6`v|syO)6M>r#s7solC zynl|`*p>bcmJAo)?aSae{*9AQI=aJ`*kPKTZJXGYws^zj}Rpm=^!sg$R+J|H5MEV#G#Nx%;3S1%3@o>eL$2SWn~D<=3tE6c#jOS^feCT<#n`o3HQ7^hcyE&_$O;;eU76{hN_42DHM=ZvC}Z%NY#ljI}GL+o2`kM z0GR~wR#zP|4<89DWb(E@%THrlwBKAmYaR}Cs}!4)ZfL~@FV8rB*lw_afH;D^5Nx@> zr zeTa+LMJ>PHMJe;GG?}qiU>hF6aL=jwD4?7hnTPnX+a4Blm1@Y++5EWTJ%>bx?Jmi+9UH09d_ z)uTnZWLRvtX!R5}!z4c@JJiadY3+qO9ZYxXBFi1SR|Lzaik2FlTT0v@a%&U>kvxRj z!Ly9hl*h0NFZuXQwA>u)9ek)W_uLZNAWRs)KwLO)xoQ&s=OqcC5)3X$KK zB#bJ}9*Hti7j1Vq3O0{DcTamv1LblP>|0&NE zL9T_VbMZHIa8{XB@P{~j7eue~@!&DeFH#01#EGe}QNyVeI>$EG44I4eMn70~F}06% z{T28)94@yfa<(~-%P#AH3Ld7d3!%`1ayfh7Aiw*(LlEl1UoA_v#OD<5E@?h=kig%( zp2RMaEb}q%{B}efx_apm0m^KP7Z;MX)WFeOu3_ty85H55#Q%baUA!0k>87XJHIY9k>Uwxxc3{(3Anyc$DB?!IVyMf#N! z>uxr@$xt1JD>XeJ+Wb~lq#aym&+ec9TSk=$SLP1lsRxh0ylZg1uG>3Ym^n$S-N)__ z!>jV-%*V$z)#L0~yRI3n`lg;*JagEUSbmC=!n;#+cJ{PtTd%vrgD8PeB2nS4fzgKX zlqKL;4umEWOI9^tPVuOts@`}ucZwVPyqX4k--9>IUKh+HQKQ9J^1YQo<= z6G*5zBmX?d?(f{JRern!t>EiQNYtYimlISQncmM__P1ptLRQ^Zy%`l5E?r9{y*G=) zn8d@GaCCc!41`_mW0TIe<^r>7U=?#(swtWZ7ha=#HJ`SOH#+CLac=J-!MM(DSvp-a z?J76gs*PHM0slso_88JmvuNMC%MEE5L)2Mh0UApEcsr|?)=j#mjV~6PqXkyqOGheA z)1!&u!9s8=m&09BkKw){|Jip=d_cBOsgR&+KhbxUL4lzPER`&l78UpGy@q(&f8;k} zFR`BS3{8JB)Ses(A8~_X$*F^FdWvm7sX714g{Psb#a&UyTP$0)%2BGxB4yM`quyRH zjfBf{6_Js1Gjm9TwSM`Iy|9iy(v-+ZmnxEgf1uB*Az}Uj*dgoaBXkdVC5)(vThu?r zc9CkU_YbCBmbsDHnJna)-hTWlS*zUa(>N3QjjTe;;!qUv_^Vyf?J3M)->vo_;eX&k z|2~3kHw|z21yyu2zXJdqkSX(zHEkioeggTt-)TKEI5s}0Z-7qN=P;aM9+_uqPBeVZ z#t~^5L2y^oJ-oB%aB%4NlJ0{Do~!fsr`AjT!lQ+AyE2|%acm&;1D01}9L)zGP$NwA z9$zV00?o%&AE*@HUzBp`;T=rQYSl-1Pm15lYIFlepPe3%chP@CM(e7KYnlDVbvUMk z)aL{heH)oegckl`*9TetZx#eeAC(Pb&_%(QsC5RWI(2_l8xk|}V z{{Dkp(U&~32D;eyGiyt=^%A1OZn~`N3pY;DzF2N-(yqUOVx{4x(RaA=Lo|}R(jV(t zI~=Pq5o*ZZV7^a|yhiKlzUC}GQ}7*)O9$QuIjJe5tAEz1Jm9EMz7!e>I~RKBxD~%k zNE#Y#-3!suvXO&!e5#ms6`A}y|9ijTNYwSc(ooMn=p%o229EDdh`~84c5EbCHfFXa zGD-6@4<^lr*i;Z{$#~TDxBS_<%iU94aCLE(+`buxD~GAWl2^@q%ox+aDMA6``@|+Q zx*nW@OS#QS_ZiowigCNR(SVlLbotZlh7KakHglidQa<)BvN6vI)pK!}dW^$LNs!hk zjaC&T5i9m`@>Bk3kdXQMOd*3bXhPo`hQjga&8Xrt&b(-cc!i7NBaU~pBf9pc_?_N0 zjr8u!u(YRXT}dTSQIHeTEP$BJ@F4>Db@KjHrL?&`Kd{J40G74UxQYY}o5tvTjup^x z8nZrlBF1tuH5RBpICvM#LsRXfNpQ@Yr!E_8*G!SBfxtkEA3t1fy{A6%3mhts0BL-D%7ojqk>Qv zW;J$3L*5hMW6O*^dFT_~dt2y`z1j^ydiT!?!08f&+U}gCZ3SI1i8dErzhBzpXGP$$ zY@^MDQfI0M2+Z?sY{ILtXT@~)i4(Dy@cU3>?O;N8;D-uO^rVko87bno&c|J$ux-KB zV|`2ND^d3bvD1Tg9Yl-`LxSC0w&DeIIrr@*5&c@f=*l*w8@mD@OQIR30y)~nK|wwr zWv@RBj4J1SBE+2Crj=tOM$|tir~LW`1z3jCjNVk61T48nV3D)hO94R#sv((?wdn){VSgGIf)fzV#T%RHZV@ z+YGgaC=E@V*ygDnnLlZarygT@${N?%=OJ-cnGGk)eJtjh<{e3PlH>jzE|agLB8N}? zLuoZD)uRSWPl)S7YYJBWxA$j!lkZH@N;~moBeMr810qrkt#CfcJ!^R z*wk4}yWKnKhHianZrHv}xKA|ZW&MW2FKot{CA$W0%ije=t4>i zIY8_DYq~`j{peZFW~hL9{{APWI)*mdOsx9`y1@$Ca_OG{+pb4 z1PDkd$775Dlw1lN3dr281pp)f04OgG$RJLDKmY+E@s$nn8V5oi*p;v62Zzsx3>WBz zR7csr{l%3RBLlIN)~gGM^O6Ms2norMqk9Yhsu~8qga-nA=7%7Ipt>aF83)}5VFMpb z@b$ACAh-ePZl z1~?)kH@oXY)CN2N{_jKcaA@T`A*PU(_d$ULxd6)c0f=C&{c^BDUO3f1U4h{DX14)A z{-ypb-pD@BipZ_i8pL&TZ!N=uJO&Qn0K&dWcBCY?k2#R@Kunb4e<4fK>*Ty|j{e>v=nVkk-6jX&2eh$c^#g_iA%?gB;QvMhaSP}o1PBU6Cnn$X z1^=-|gn$6(lk)`WgFAo-M*LdDJq}^}YLTCO_4@##_9wrA1n}ea{dI2?nTLi6ZGZbt z{ITr)vXIDtUxID-CHj$-l1IFOhCo09zJrPYkat2&0SL?23HaGQ=6(Ae`I)SQ5BOon zzRL~4q6cT=19-y*zIgZ<+5Zkj!|^2^gnWC2&}NI6L;x7&U1|l20JxTi_y4s8{GxpC zz5g*y{Y8KN{p73Ap{4B|!0A2s6~#D$a=!me^ebpU2O@#SWs|_E`<3|{_?6NC_wPn_ z_`WRz0}4tA1)4$>w$}mF=gGUX-%Sj3JZo57i$3G!c@=e}Cdo(tEPKm12Pk3jq?q!^hzRMj((& zf*=t1CD33Td`8{^`0!xh_)`Mr(Srlx?BRj%u2NIO?1?J(duQ$0nWBdQADE`?=@MOa zb8*R;z74}Hef3`JUWD>_5x#&pF4}pP--$Z!+s6NeYU1g_CR$h%RUZQn=pqtkaSOvs zz7MS|7iph8ZPqEDafUA2;PR-gJd5$FXMX&v*PT<}FZ-62D(}1*KTqra@q**cNV69Z z!t&?7nW-_F??TT+Pkz=X2 zAf9&P%OKRW_Ka;C=2d7i`+1Oo(t>7-npmDWT}ASJlR&UsnqgIJo9FA_mDxjd6JFwa zHgf+h2GSm(#GBnfZ_|7(066ZfQ~s*+k`2Jw-1*?SmlI(;17nnZQ@;3dp7R$u)$=uy z^ung=+rYYcX>|QP9Ju^pkm9edVpR!Mp`PTc7pTb2WPeCq+Q>+4Q1KY6Gd&*m8={LB zUhFOcPsdr>(*$pA8asEAmvIMMdk``*Ud|dyMXAf+K8ILN&}UVTR9RWa-4%noRf#9D z%ass{k+13H-<(me;iHVn`t+%c^+LS#C4qfIgw6NtZIDjA{)N)v?lIYVRBdfrlm%`x zcHWvWZEet)PW5zg3ebz{F0c<@Q0liO%)OO;IvH%9V+bZr+5}{+GWE#Fm=Kk7sO-4m zjvUyb7-ZWE_@fM}u7tTdjv<&CvF~`PZv^bbW3Qs)dsLr&b0Bf| zrc0gevJRpG$QO-@gM#oZX_-` z=2{hfY}N*S)uFVAi!1%H7F_OHw|A%ry^Sh^@t)e43d2!z;hF$nN=INMU1NRQGiS&F zG`x9%0+Zd^+u3;u|1=z4wCO~J_13ddSTFc#@SgU!HE1;|eTaf;Z(*>&60K(aP>D-n z%y^K$2((jP8MI~f+VE$7;ruZfb|o;%;#IrQESZ zgXi(TBYEoRbZXX)6jp1Kog!m%H1gJ(sMY%O+8d0{>SLjE;w0tu0OpIMiMB4oHuX%c z(wIH|?ev|}CD+SAy!$deydsk!%@&^k_JMkz`aZKipGRX6H%28wjkl9nQfyPcg5UHS znV5Xy+0o;Qhc@GpuHN}*9+JnIQkS7oQ^3F=T==@$aH4>v$q7^755XoWIKE;NF$xK) z=T>ZMs?-~hWNleQF>vd>S310R##@u6D7;|depmt>O@Syf6SBQFD#9$^15xqeLognA zBlp=Y@Fr>o_t-tgXkT!lE`<#h>fHplwf;N+#x(ncF8ibq`UhWQRpRL_s2~~qSFAq>*Q&``3YK?`GQC$cUr`8b|_)1l%vd}MD^WzgD+r~ zg)Z3HSuTc#CFpv+Vq%F5+xD47ih-LG+VPa+!k?p`9~1a7Uub0=nTQond*L7_`IN_J z)c+VA$q3%vA^T5Y$%FcgZv9gxZW!ULEz4!MY>nuess=iD>8_hoNOSV+*27Mg)<#KJ zF(f>WUUe~CQSsY+vL?nL$w&tM1?fJ{^`W?Bx!%`aC#`e+(jU!UM}|95v6{V4U?iOUzJsgUd<7 z#P}}^BMLN(sIxfNR+(r-b7FCcx)p;6w`23A=|94^ho3WHZ5^4~G#(NlEN#oeH z!5A}Iz@?+hJ++U3~!{@Qw##kfWbJB_@Hx$jw5|1gHCTK=b zu&cpTe{w~WQYayZPi2~%@v*W?ZRI8g%y!a?m9p}dO`4bH8NA6?ld z{`zG`9d?iE628#*)1kC_D=UAUcQqY%pGkydhi_Ss7jvj2H21ctz;HU`cuuFldhp{P zfGEPG&?D?T=$?_-O1oDd#}bYZTXRk%S{eNyvSx!SzH4ao`gtl$7Qso@o1`O#{CI@WnaJGP8||oj1ajP~b^gpbT28hj33D8r01y+IRvKbe)j{ z_%1}JC=@gcpf`pQkG3^IlrvhzMxm{J)~r^c;jJYQTQQp1xO6-`Ovxx6KW5@7UhlCz z5MX?kpq5)jqZ=oApMcg@p(@H9_c9(IuxXL%lURJC$D%L|wc)0V8TtCNfC3GS-xRPvk%i9c34sD}{zq(5*k zjX4q0`TCi1`rVdNBm=UZI$$Fl61xqAblRkJ{v2pp!`NV*-PLa@pIbm%{%bSBvT!S` zwIN1!I>hb;*pw9%BDYX~8n3-4Nf(ERAx(kT36H2o5R86S&Yf6Q+AhV_I;d(p+HN{7 zV2BwJAXv^x{l*CHd9N4<71}2F7NIk9mA($T(;Pp*FxvApkyT84h8X}o5~CT#fR@O3 zW*uRS_y=K83|jDFi7K}0Dxw>eRwp6zEWz=2hU+ruI8b$$U>iw&VP^lp9i2pC!sRx@ zB4Ee7Ie?N(GE8d6%dNS;hgim!sqa*)JC48)a>sVByl0O#bpBayOqr3Ok%?)jNa ze?DfD_Vg}vl3G8)Hy4RIHiRUijzv?p$e)V-wK;sWn)55 zLXX4*0>X0AzJ}Upf)R5I(Q^QXeov-H*^2_|2CZO$ zp>`W>)%dK@3+$b}_L~XZf5Kh^#+1?otUV~jMsr4S!>hva`TFjJyUzxcw*|}?A3)e0 zrRbKCP>k&;)@>Es>djhd%P`Pmu=DlgSpHoKRep7Os9@jaj0=Ni#(mSXV||o{Vb!Y3 zSoWliTzfN&Op66!7XBp98Ol^u6Fje&ro7IcuJGKBs|rsv+lmb4;YhBgYw5-~eUq{a z$JJz@9p_t3FLfgK+ys(v&1&a@Jn%r;jpryh3;Xq3{PJR2WnV#Z14lipFVfKGV=JG> zy&&^aJhz)@SYvd=5A88guqgz(@_|73c=>rn(;#z^+%#YjmECZjNJGP)y=12Au9~W{ zUxM5B{**zh$S!z!Lr0DiILmI-jXj>w)3*RpGQ7#;UJPYJmpOjRWrUbq5iHJ8mzjM& z_HPa6nR?Ah@V)(4H=snH`#06EH53XJ^~`>{#mxrBfSYA%rPR&)^N0AZTgQyym@=)C zG@2VLuA^NK=NaE*FEC+?14AB1?whm+1cx&;?NP~uV;ggbnW+8~2mIy*u^8RF++WE{ z%9EXc{nil-I_UY+HMJazYvI;zH)d`7casDv?cL6Xt|F#8_}WWxf0N(&B&cc@`$LIU z00Y|efP)OBtf3RXiCNGlBL3uyR$TVXc2)P|S_5)CtFi0!{t&2#5!=d{b=TD<3hjHr zqx@Vd_e2pnY}E|Pq!ba2PBxcNdwLOkx1A1O@A%8GBIm~AszsCFK&<=h44`TDn`Oer zE#?HZOJS0tBsVI0a10-O??j~ZCd>AB*y&})RFpKf#hA&LUw52k)d*I>VjDZ0#ahh> zy2rE_#|F4w9%PZSn~T9F>iM*ie4QKPf|)`u-B^plWESM6cgm4%nVnT@K6?w7cVEd1 zgXTGCe+&btON6e`UIET|aQ~{O>wRy0UhWmk3vo&23UU%+;@4+cHk(;auZ zOf$KB>F2gs7|G^w(1_KNKKE)udwu}Lxl#pbvIO8R(bMcKyOoR*n*#>wrzLWwr$(C ztENxxv;IL(<0+1d~bJ7cU^(8htzAM4F3vLQ+R0 z&A8How$K68MiqEs%A}J7S~qai95C0&Hg3m?exG%E?Q;9D?WcYNrF5}>KPHFn`4TfE~${`LW3qwv@MOOQF_uyfpO_`5=wA*1xvD-F+JK_~Zd!J;ht zFuzgymA!*Q@Ti^aFozva{OplCjU!7k*|ci-d=NmrfGhP{Z=5OTIbZYjC(d&^{u8TV zjb2DV%JPtq+!?IB<#8;ZI>C~bQFG?!^8E5bhZ`LVg{Cy>%>z-;7C*m1Lac3s4*k{? zx+ZZrLjr`yh)xD?>ppbS?t|xaI(OqS(!pW-d{^yoNj_o4&U}m9PV9zP z!aOhb=!)yTPi`^aKz1`AgVb2ppUIQrau>74ZD)swT4 zab=2S4#utHzbO@)CNFSs8zc#s#hc2VB^V4S_XQq5#i>?AlzxI?AIF);5P-fMI@=xh zjA)`NlCLTT*7==F8pu8e-fjoxRpTiIZ>rtsZ%2<40~__Fn9F9I4me9r^wg&)*O$Kg z)!P77gq+I#*^=GQPhS4uB>ytBaP;wvp)Q9dwa49WVOV7Je9MuH+R$YT!E9wh+-bt6 z+$z3%13?HiZ=QQ7iu2Dbb{|a!^<-AEvV6OW^(#x?*inISP6>xpYO;+6*x+)i1Uq4;x5_bQ2iXA9u7_a{t zxr_#gmv@oMb|xlQ3nyJ<9R-`0&QOAjNP@-V;*&zA$D2(3&6-tmQF3X;RpPy_mCp=4 z7O4pC7;*E$c>Q~5>utObcPsM&v^Do^cvhHRa^?O*TPpHUlw|kfDp9u|L*457LQ=CA zBnn-_ozsFpoFt}qr-_ZW;1yx_8wy>P()kO`+YJ0u(Xa2`i;h7$%R>Iq5gnzs@vuKv;dH8KKKD7faJn&vxr*TQ+d9E0wMiQ0H(tOCs}-wc0fDPJvgOIV=6k zqwne8+)~gs?1XOqKKD5$RRuY8%0?Y4vFFzz&eZj|@0ZWvLCW~Q$*MZYeW`4yC|}G$ zN}9WItILKd>Sx^i5hhVy_?&#+;Tn{7&(I0O(FDCCu)m^r*_d9fa96tAbuC=py{&A+ zd4Bb2lsgk(;Z2SlI0c@>g-}bO_^cf`AO4GYZ0cHp4@#(F=VLT z?+j51@E={=Z4e3)4u(48QI&bJu`p>`%rlbKI2_vW(!!9Qk`D(aed72Oi5Ty&e^L%k zaC|&v{5+uQNKv6MD9Mobuq>2om(C7%$(pVFbca};b&`wDI=94^E$`bXwqu@(RWY4u zMj6Z44xFQD+m096ktOe)KnxF~k{2<4Z#)%c7Ok7g5ec;Jw#AJs&DvB81oI!z504m$ z-vXb2G6~;35UXrb-?QzD+?kN_bghfpoq*etP8vSdF*5ilGbZf84{6aK@T&`Jk`K|n zbpmE=Lv|4&_)s;@Jm9e>8ji_@Vr13#+r7V=hp%x0yCbZ}c(Ck8mVFAmX!T(~gWiA^ zP`fMSyIFVTG4(eToQs!MSsrqL6k~-4!rwQ%oC?l#ji;?+_-b!*=kI*%O=-7{^!djP z#mGJf;nXjDLv8-NCw3pL26uSTn=`A%%x4JH;vp+HvKiTV{fX#Tlv_H-58A|QA1O7o z)KB$ItKos;u07zEbS-Jq|E&5~ZhW|w6U4B-E5IEvR~)j=+JG3RCOEm6i%xe8Sk(Kv zNM}3@_z}b>jk=;==N^UUKwzZbCJBsx-Kw|LoiOl)3Hh$37fKj#*coT4+KYo5caw@3 z(gRJD)yHT{CdAW8p=9I;J{OhXu}-SJ6(u#<$ddAC%nuU+Sn zVJT`B?`?E8KqJ?wXq%r@0AfS02u5$^2^*VS!^qccq?p?O(D?Y#Sjw%9#B_{OD~?97 zklUZCvxpR)!`#C5olfSso>8R0OCm9yx#{k%KgXum^`^|lAjz!EEPPbUz4P(wq{CY= zfDFM)+oF;9?ZbXcBmkzs6zk)*Fg>&X6~sylG<;OHa-L7zEMW!<{2{rJ?~#=!1Unm| zA|Z@undsy{z6#&GD7zH z`v+*B-uCT35jM8}MA(=){wGuWFT%#c{QpAO{$mg=8UV?Xb+ycf+)sd#O@TOf5w%@_ z-6a~!g%K5nIeZGHs81R!LgXopAxI=5zepkYxQ)U(7mjt5ne>wNkn^K|@v&U>G}-mx zbJbOonK>{jqA`Sd1r=JLs9_ierSUHt*#iv>YEat>g+T+cf6OLo5P!>Wh19}{a}X_1 zc=$aa2oD-+c*o^}@$05ERt%VnPXdStL7?c6VBX1qfdB$x;`=IWcog`YK|hE&j~?VS zPtn01sRe7D87R=fWnh2e(+BJ|>lHYxs;Y6e#z9~RG)9o4Pr;uL?gHYaR~_(&5E!)) z6(k1!RUC#7oSkM_Sx#kfW=0%M<@GoHaIwD_0n^2Zec*ykBM z5OTmL^;Yg_Za7kzejfuld1EL!9J;?i8wec~2@XThdAPw>oe&V*(dPnk$fMZ7fnhfT z7|L;&+pCK+29PQvgn|2i0XA+!q#O-dz_Sw`puo8dz3@kMr zfv&-Ozp^(){7Ts2Z-aiAgnTRRpoISL%;osQ;(_si?SYK^1pMhV>~;W(ybA~g`zqbb zMS%hV&O(;c=taJc5D56r#;pnI_)NJQ7$Nuswr22sApm+kxzQ)r{`BN5R2=p9>-fp2 zDGP5e{+nE}Yd`o?UtUr06+mDJ%|Jjy1`R>LpDKgp2lZy2;m5jbf7{b2#xR&W@g**1 zn*@s$_Z1Di)7j(r`mG7u&7ZUf`K{Rp6uo20(fe|<)B-I1C;JwE^d}vtN9fzn>xX&b zr}_QIhp-G0ULE$;p6X&C8<`L9$98GB z|MpQqu#MRKbFV53F|p z7FcH%V|FH7Y80g4mHeU<Ja$FWB&w&uO%GjiLZm46eOh3}7RLM(tjwu;}o z*l9}Mz3ye0;H6+l*>^9`Q6_Na?npZJZDRgr+UQvo&y7t#J!55eLpjHQA6~1vycJD3 z(?;io_;v7mZ|Zx9YgPmQD^&iilFEKvV@xARHaYc=eAl0;0ejRXr0$iy>F4|SHk%}A z=hKynv!4=p_BCAIdW%jKvSMl9KiEieEYh{mevE_J2WgCxqmqBn%}CMnw(m=^);I8r zrr!b6e;*W((CSkt^pF77a+lk44!e)i%8WN+WOOCkQB@*di(6kjf)&)1TyTYg!QjgH z!=Kh@Fsls|!8tO}`pBBd($vD6QR1piozGWzevq1@zHlPq#0qUj!gncFT^+iB6VP@?nmvIk3^c9BkLAg;2X=P36K26=4M3T2y1x z3H9&$cD0!XX@j7!@-=Hz~)044{p{u`tx(naB~OMe!5xa!KS9uU-QHnDGEX`VH;1@uC^ z#uE?!fYQ(oncy*u18aTP&r6-Whg*THSY7`yO|AbN8L4`8+FdXe+bs2Iq{@Bc!G}B^S;u=SpX@B@;X!`8?oS*kdN}; zYjQbmsN6Y$6?)@D(J7$0N#Ls1i6$paQ^z) zN_8n47YQ5Do>&5SLIY|!Kyp$DEE6D=Y6MpXrarXZvD8Dw8$)VHZ-yg(x#)((w7)wF zk>YQ?Y_NqN!O(Fdiepnh(!KBzlHa(sKBy4}!h_Jkkje6@mwlYqX)3y~r0^}AHM1t- za%$hRMm5&o|I^=#<;Wn5bo@$0&0!c_y?v3u~N2u3c+RQwhPv3G-+34q{9=iE&EG$PdK)B&e0l$>FA8&>&NP=!ICpiYO*u^Mdf&>zfDhxG0+@?o-tulvd(f;+ z;j-=|rKVyq6HwgM$ZxaitJCXSe{`OG?DwjataGl3J;{Cljf5faZP>J#8A`h+MI7Jw zSbcqiiW;?_uf%n#%p_mg7!;~yr|fVWw({Rgw)F~4=K6>ZM+(n)G)Z5> z?uCKumH{;%jd~x0Q@gE3Bo=*fSgoIELPaMRESG}fQDxrSqYHiIJS0z*7QL7jW2w*_w*PQkpQ1eCk zgPh9yd!bK;ZHruKbvTb+&I*LDlz&JXbgUugK5Y+P&Z=LK*;hrx7ranO=%t0AXAa*_s4}+S^ege|z zDpqT-hbu%Ari=UrzvLz1k3BWUAX%W6*&GR7SAG53tvO~IEj|mZ71>{UMl^CgMs{@k zDat#j-0tZK?TZS749*CID)hw4JpI4wmQiqzGF%3ZhqIW-0oNM8JuNa0UJuR&+>ZBN z;=CnR=1ZcWM*SPTMX3>du@hNpHz1C0GrkM_KWzbP+caD5Xa51oc1aP~-{My&oNPVGM81x-Wt z{)^Zh%eil_y%!U8i&+s2)5yCwbdoW#O%tAEVH>NgK$RhjR1OLTX{~Phx#o>2I=JjL zX_twDN0l#JL;5g1DxCA37X<)PEBb~F;b11l{_E-b-tu34Q3auy8+Pda&wLKsoA0;G zqMAO7pzA^cRxz(K^%!80M)O&jl`a_G7wIDdgHnDE{$1nY zm0y@y%`2cc416AYXB`V7>3vvV3@(0E)e2yRR3E>8<5sLoRg1toZAJ`nQtR_mBoUr= z*dj5b)qF%Scq#DJ+-)c@G2wVliVN|j7}R3FWGVPwI|n?hO&sH21WA&r%b9_nAE5E^ z%y{tZh@nab65rc-(^V>zd*mv~4iJuiTL0b95jLl0&vta8Zv?VkoP96;u@a&9eJu!T z-qY&-6%c<}cDY_HV!wtVq!;>z!Zyx288j51)mQkZ3E`%%>seg&a-4(?8STuq>eqrI zj}eORqUfl=J?URU#z@%=r=GJiMC*|Hm=ll4tdN-oi*`>MEwH@B=7oY8To4E7;hHfc zZu~V2e!Ff6^j=v)nX?vD^-DN^AM+0$pU|*R3sk!Wc8I3-`IiX^aQl*&DotaUc{#4C z=XHza>dsxlrnlwK3X`4a*qjsWN-F(-qvu@p~Ida>F+>&LCD> zLGrrAZhf{Vvr?;6C(?u-;T)&nc>^AmY4%S11vbCcEy1k}QWS~m4n@H1QCCZ_T%n5! zf+q%pklc8F$uJ)N;I0Uj5whpS)jHV*N*b^z-^nTF(Yfv8V!Cwej#5DJTCnEGwhJfAeJa#K#CQqpx9iw`k&v%aqHWM~1Uh_a z>$%(5-Bx1pz>F4KR^ZSwNoZWs_M!{9WT3ESR%t<6qg?j+nO$)U#hlotwtDxC=r>?k zD77wPxme%CGl8{hqhjD_)!u1rU25)r5YG!N>7JM>eczkAr=9&q8*TWaXZAlQhH2g;XVZMF`d}to=lMsww)!A!w3=XI(?} zq|N~PqL(%bLwngF-eRg-qvU+p>LhhBG1wI@GD^G7hB`L?G=h;*{j#Sfzob7?l5*!? zEyP$AE-d(oLXq-LJ}Kw*)pQ* z(vVf+ZVu+YtL|jL;&^{^R`7fHv;|W<8JxQy{61AC&7Jbn>iO_j?Qa*o4r;%`CwgDh z{65I#%Y>Wi;!Kw3c88j>uQ^-g?TqS4>icvU#LmC@!@s=y>m+ztCF)J73DyQa!497s z8kel|2y`q7yXlb%%!pP;6U@OZ+Xf(RIt_@Hh3WLF5)1g}(BCk|T6i_aM90-&Z&>uu zo^Dy<7L&;uIf6&PA6jH$rh4}qm86dCmf%t(Ur928JMFD??cVexgsdSRoxNr1JUgGG zcf*Xs6fyy$R&@>xk&>xiL*)X6Ri4pT;_L8BcXqZL)`nyxaiF{J*9KRrEfZVI!*iZ? z9MpS59d0rV=D-Y+0z0Ep4Hm8PIkL}2M3GlR1-=l}An&gfren25XKTKEX0wLx!lL(4 zDPa|IF0?Oco74~60F3sIZ)M6n(s;9>@b38f`YidD+$1>y?IRDR@xRnG@;qKmpnknK z^F2WDGR|dIHA>^zE3QNeY;*gPiX7yB<=0!GUPO^cXM@ZIZt7PjGkb=^Tdw-0R5(CD z&QFe-A;B$~vpMcRTf&sDxqRpOvEMEl%A~_yZKT%EM^3IDvNA*|)umHBbRWAu=;7-N+yJerH?l zWKA6HH7lKvpxs3dk;*-7msl*7c6MU_^$T;S`o+ESCJGML5j26k0Jp_a(1Lc2sn zen*ICBdMJ}Ty2u~A*pn=@|`iPht|V5Wmc-0*L#DfqHL5tq*05Qu zuC-u2lcWn2p8*eIHRLu!F+ARrwoA8c@xo$DV(XnJdyJytQS!ZLzs<-^Jzwe&M@a|A zDn%9QDR&V@&Kj>AhVPmNhMOkLgh+#KYS%ucp*X9vFWo{Es}sG8pB)BnYpN6;+|2cS zNFF2TebkP%f?1D@`0ZOD#7xABEw}3Ty6u~empGmT7$8pGOepko=LR<51URr&~VgXA{yslKmnMW$XyRlHKz07&A)n?s;Bn zkAz*vsF6(;a{Qg#(V(V|%tt?vQTkiU73-aS1){8)LA|@a;^t~%OFqlNtOL;CZ-FJD z)~8pjfj-QORB-g81Uqo#w%qRXMqXp*j|#vV?2Z&g`thdh~J-8a+3{8nuk z^ppzweYeuNPJ9nSXZ28=wbG#&W`wkwyRDJ;M;i?qr3t32Q zIrL;t)#g8HDHh(oQ6Ul@*^6FThsO0rNTz3i)c0;1mSbl^?@+qC4BQG@Y=WPg^#8_3 zsIA61Kfz6MTsG};RL6nXcCj`&X8mAfN3Q8x{i}EgMn~xSXb=y#NO-MVlfs?scQ`~F z(ir@%OlzyvN!p#%9u{%e{el*S(uxCUgDVGAQaG@GJN|a*G;qTDdLo-T#0zO0VW~gy$F5fmH+Uj#3~=pM6ZmNMlt^Q6RQZ% zM_Et>&Z}Z)`TJ|s>&{~}cB6hhWhYVRK4ShOygSQ}>x)o=`Fm5z_)2s<86n<2mlNwl zivt`$CR;?$E~inK9A96BWZy2YRDTZ_Ratea0QHN0sJo_|xHu=TyDrrzu3?n)NZYR8 z#>(ZX<{~kw*i(L*)KlMvhPoKpdw)xx+kz7&n296P`aBv6nr^{sp=*(6BDVpxn(n^B zqHVQJ{xoG)?CJjW^w-8juf!8k6;tplaMrt~)^fymT73a`&!6DTfj_=JRr_xib|-Jy zGq-In&Mw(|yW~wxDJq0t^otCRxN!I~+$vmZqq-RK^gL72o+fBS@;D=$8Z{mK?p-hW zmaa>tr+sx(Ob=%PTMA6b)Xd0j-c*{#w=J3e?XnlTQna~*<<1Aq3*Duin8W+HG56mq zl{a;fH}#o-iM>tSn!oZ+>c%d3dMN+C@ECb^B+Q4>W`fw6-!{4{2+P$Ef9lhhR4lPW zCOL=_M0z@my0R7^lY59vdX-0|11TaJJZud%i@FL~7azJ}yA;P%>~uZg+Q({b9OQh* z2J0=cKDG8p{jxW*hM*+f1B0aDRl3HnzKcdzu@_)JUC9Q&`fU^`dg7D`?^m@UmaqUm zRzW)x2&2`bsP-rW)S#K6&n<%&kTwGLBefUi=4!d5xYx`AH>;&@?4)8y>821P4_aiZ z%_AaKRLbemI`Q*lEr#;ZIyvj=Jnd_`C+F$w6>J|fych`AzoIW9&Q{*fz_~|=BH5Jw z30+RWbOe2|hevxb{JJ_q_ufgk)xeM?MMG4z0{H|Pp}-F!dPADpR~dm8HttXotGEP7 zFpY0voB8K_(b6l)2ER_BSJ2I{vYROwG+82UC{_C`@5LJDTjX$=JI}CBmsioSFBX^* z?2IUkwOh1mPtoW?T~k+=hRT+u-=;hokMIb9Std^YJMq0L;=>hmg8JbmI zc)Kv^*9(+|H!hcvjS1?&`Jm4nyeJ0k0N=eks4nDl5TQ*nc5*&qkl0l5xH56=s^aVm zF0(5O+NOqc9LXiJ7GUGmtvJ--l%sA^L}@=IuOQTdBJt{uvzl0i5(EnNk3mIu4_Iya zN^7halaXPZTm{C|5QvQYFl8N4M|npYjTL46s1^^e)J`$jA%%ops%~K5=VaTyF7Ty< zwH0{*bnw#g{OBP>*PQPFqP}1>q}y?L3{iRQcS zDfTJG@Y01m#_ACR^Tq}C*Ru|Fq}}LWT0O2iT0+NPmIk$r`?_sOX(AhC=_Fl0z=*p# zasLUf{r4H6|D~@n{I~oqE9bvP?*AXd{lC!H{(C_Azv*l4kSfX-^K2j>L|twm^VUFT zT`$|BRuTkAC?xrTk5pa%T6B6~MZ}`z^O*o}N-6q(51#(!&GEWv`{`MJsjg~j*hx1x z+dj!QcdcjRjtpSzDIo3#t_txld<_QkR{}ECHI^nM0D?k81_BAbTU(ROqriBz=jQ9c zTm^*|?JfQW&A$Y07SFe(dZu7e_zetc;n5EyLxZ}F`_UN3=A%_;8bLm5H-+&91cOW;Capn-)D&k^Q0h}S{_>Eaqxm4nW@K@R+Y zTzrD>f_`%1_{aIr_RN2UepjfwF7tcVfqQd^X8GHD?5^<1=xWQ-wLWVsYFyB&vd}gYxg-rcZ z@NnXUcYas$;OD>)`7>MUxAM-qdr;nYTZ- z&LD+A1p<}+g9W_v|)7-6pq)nCs3^?vH672o)n{59{98CZFrc6uRwu|HPql7cwI10q1_*N zR>&XL*>(f*veFGdFIL6pQ%uDm?tGVNdVoHV`wu-gS~Q&wai);$ehuGr=6~#}!B+`9-da>K;MRK@Bq6FLcmVFZb1t{X%qq zy>O7v;MsSjx4%!22+kZ*Q}=LFT_PU0KXZp2)K=P!5@3nB}EeTWBWmOY_z;+W^mn-Eo@<=aq1duPb^+=whR%a`SdC6R;$ zrB}e|?gtp2b z_r|pbU_vhP%$)|OeuIv5<9pe-xDr;<;q;no%1jimYU1HHhhxQRsH(i*nGw+b3$sn1 z%5D&fYQBc$fo+R8p&uMFgU1gfQ^mU8uJv)XF6}fjMz;sfq>P{#i62md-e+25xB_w` za&~#)#UuOm$DB^F^1Bxgz81;g&QzZ^9Z$9+4)TkPf3D)!C@aAkMveR-oP)$_gVr_3Lq;=l|{v7s`SQn&2Ip#y3b%sy>5-Zupl`e-G z+Qmd6a#|UH8U8K3WK=j~BCKt?K>8;jHkCZqz8vG4JYms(llAh=b%SiI??6KVV@9ka z?;@ZDG zuhD#aX&{?TZY+~4ABKd%s5fuh&c;}J_fg>-z$L~<=9;03j&&4E52Vsc4$W5mn?V56 z*oxJlX2Eee;$)5)#**(tjKIW&(8rH?aLcSi@@DkQ>xh^X9SD>0L@20eR4m$#A+(5} zO|Vfj4rWgsnn~zmtVCgtvlS?Wxd_t_m8_;qM77a;=(&hBrEyPc>+7{Mbr00Ti#ITD zIS>C7q>@BMcE2MvVDuyQ&#!kQdmnVWU0$_80$xu*SAIR?!g3|JUvV+#%3(zYO>sv zyrWjqS$#Yo)A7ym(8g*Xl1~g0p=b-Eny282THOPw^BLg++Y}i2_rT?9VIhPU!ZK=zN~PKzu$_~5C)`f zxRP)C{+5i;=7<$rq*155ELKUg*V3d{%X|~4*x{EzF$=Ts=ssJ`?8wL8SV|bD$W2tI z;(E}J{N}4wR9kwAYdY6<_GEiXn(MQrCq8-%M!D1xMmP7?D!>HS?*0_4h}YSdQ)jAh zhlH|`R(zQ6g=nZJobY1I>|9iImKc~xh6NC!96#`eQ@T=^?6|Kk3N!%k*YN5wh7?5- zaNsmlT~Y8LZN7LWau}+vKKlfetA^_KC>YX96Vosy%a{%MGYek4jXK4t-_z^>X%kmA zSf>B|)Evn9)T-c~(P?e{J;&2@Ss#GJZFLBczHs2m7Z#ET+uVy%IN zzFabcyDgyskCyw!GbM-SNUoEe_ewQ1dc*m4Mrks_Z#5sHGW7P9K4}*3r?%X#^gep6 zv%7Q=Fyvjt5TyLJ=w{kA?Rq;j2@7tGlqh1wnshtqP;%1@}m1>T8`+eLOGcZ zqBOoU@XCilppsjq;O9EzojN2;67vEzVHFN;{TT$COt`OFHpQb2E52E}fNHG- zt>L+E23sFZ%<~y-F#p~T@5UB6R@!ag)vr9+bUrXN7Q$K)Cuh7YbT)YPXf2NocYxt7 zI+sYpNUAx1L`47UlrjdPC#z=kB?4(ZxF`zV)nmH6Mg@3KZd#i^el^f&@eyr) zT5JBK!3RF>3kR)0O365rAximF=3lQIX@(oIFmDuO8pALMG*?m0^pb~z-_E-764w}CyS#DhDaB+^viQs!a zeqVK&54?*=x=pk3glTMaM@%XPv0;;|yHTh>prV?pM~5H%N8@(*PHF+TpOoY+vu~lh;hpP>r@4S9h>pyBXPG1?X*J;Wi}h z?3Du9VA=Po;jWlvu3e@sX*}IqrMZ`}1#M^b+Yc4?J_|f|a8>e~AAQA3!0HN6 zs@v7qJL{-wDQC{9+Wt7`$cS0}Z4`ktQtG#n}EUt;iyi ziY2tU?|u}nu>3l|w!dC*T&Ibs+y+Kk@Q4Zkvp` zrEf-l#R5M$nu`)~fh?B{pSII(rknK4?PG~N(c&nXppS3y;Q8=-a&*HKN-QU^G{F%R z549mf9tN4NsRVNU*jjl2QY@Q`SULBupu{COZ4wp!__!ts4y1^YLQqnaPb+%-vE& zO>TgC<3bSHo;oVt6ru6ME_?KA!#ANiBPUd^yi+RHxi^M4z{dx4j9dPDPNYWOAs`kaPDm zN)e9fA{(!+0Rc41DzXZ7X(_%HHt;XgyeOxYbz??w4b09yuxUW!mIy@O%)i@GcGu*g zT8d#}!R_x)QE|D=|G4ggAd%@sND}v!l#H2q>{<+|YUFx(f{w{uuEqptMf1aFm;K5* zN@RpiQW-AS6o7qmMtOXFdvZ;kriMuS!u!!_-#sYJl_@gWMJ2D1xg=W*~jgdy4JOi4q>H}*^n z*5pd{c?-dOy$XpkRidmigD7EFk}mgF`dC z0q2N^4LT}tENg`T9B$tw!#XA^+KknDARGJbqMZsy}xlY;Vr z0cJ_tSwZSi9A%r6@4)2ru1j+BSrSof(^>DJRfZU%qTdXd{^BLz>$24GR*O1iO7fQ*Gn@hhBk zYN-3B&0SAN>kjzDJP@y>aAr1!b@--KUQv}6o&Ei5$L*^u%&}JpOdoT+z6X1>Bv0gt zF~x-#2fs}Qk@G#KG8*$7-Yy;ZN#6PC!HOPSBA>Hd>BHK^V&GHEi-$R;y~Jp{2L6jY z6;jQyIQKvh_w1~}1*0R7@{yx z!D`{1I$H2Y?WR_c7<;1JMvI8=)7-}D=!S_!<(K^A>EV{VgHLHrvm!=SZRJ=u%oQe% zLPS5OJ`cUhiXMZ5oqN@a#Zp8yr%eYoZdH_>`X2DZYb&a?E0`T#}_iu#yc0ATJc&sscH3QwghwHK|##Qi#m8i@`_x& zxx#Lw;Wh6y{S03p&x^gaA)!8`Ksl&mJ&k-ps!$FX(I}7W@@w+yD}dh_fGS6_eJC;0 zrBv|!yvxy3ELQzw^zKRhXaxR#OUtkZOnFgbNCy1e-$|Pz&Ajub3EsRvps{LzSyj2- zi%>s~n;O!P4~q7p=}js{@y43*3lSth{ytFAi&(IrXhhWPf*2jXbE$}wc8Rs726M<5 zTP8k#jsBPl!n=hJ{-yX|TxO6mQm@jBqdIf{F+MD&o>YuC`T(j-+U7iF$Sdnxu*=C= zkm%=(&d`uH=I=_WD&21@70uOQD*xLF5#-Ma!I-C3mmb37GEUi`Zy_e#M(lWj&4-|j z18y-j-NnRoC|=A|uiQIdhY-6b7pSE;dZext1QRm8822*lB*=_|1T7%)<%wKz5xY44 z(e{}l+$*$T-MJp!P31aKnZHP>)=JqBX-AFx=BD_w2(`?M2%j2{t_Oq4q)hCrAr!Ys z#IGgtLQ1=4e=nC(K(kX(!q_F6GSzboBpO*VK*>DJ=FAA#q20JT3d@^GNp}LJv?cl( z*_QAj;gQ;)s5>;1y{qPbr@}h2_Bhc}R-6vv)Ri5M1Hg3VD zC3GW95bkx7&x&xo$u4TBZBKKJTEYBOkLVF=E{Uwd>aI|V#j>z^9ER}?h-d3yxNIe! z@_?yDiqL=p{t*vdR(|MA>2X0O5Na(TlEhS>DRZK-vg3-}t6;k1_~I_$D%0rP8HB{+ zTUdzDDhhLeQ8p|CD$N)LcI$7Xg8jcqmHbLKb&z{jMLdJMmCu-n9Ky>)J_u4Q_oj=D zlI(1SzwBahIa0T5y$IMOQ3LjdTbPb)ChfodY2u-*bs|F=im#0{n!O*oTDD6&A-pt- zRp2&?yH6|n%v#-Qu1un+7*a&NL`lq?f|iaK7THV1`AGtvkd}byEZx-B@CT4)I|X7Y zx$X_rJWS|Kh@WG=Tj;%9O$OXeuPM{Nt1FK(j26c+*V)H4{%pH=*rBzm-h@W))O9g@ zPO}tOIjaFOHl>ad&wNgd)hUgGv@WEkZ4vrMs`fG~%AJhkfv4tOR|mhq^mf+h(^IWv zs}Ka7IhMuq4JI|zo=Qsqba$1i9DCh$BNX(xnw0Y5113~6kloE_^s+db%G9~sw{~4~ zv5k8EOYh!?Xb*gANDc1gGV|31Q$?}TA7n5I14l)>w(yj!6If?;>+qhPzsZZ9Z9~UG zG!zFb-=}xmePdPtw89OywDcg}J(cog)zs?5y+ep-2rtvlcA7`8Z*oPG^@f4L6{))B zqPbjHl-C=MPvR7>|ly_~827yEyE@s$g?9VldsR5z9+&mJ9Jp(8l9tFdm!)rTzUo!gGa-Vap# zp)TDhDF+VT*W_Djx#efv9||tt&zbRC7;dpn>bie^f#U?@F^pW86P=~kZtr0v-3^`a zxemvHUfT+~74}Ue53M9uvGmL4yrx&|qRmNfcMoxytOcUVaq&dFH`mvsxyl8H<1zHiU&sq%_wd{u1~zcT64sQq}cGMmIKY-7%IdI+Mi zwjMLhzrWLNenZ?h$#8FHi#mINH5URLmS987V!WeTR3khxx?KMjJ*ApE=-cPwtPj+F zBg|cQ|EoTHyD2j`RdMZf;-{;Fr4F04SmJwcNNQpQ^=aMr%=`1N#AhF7&xDPt`8uIX zYam}b*7Yj2abkS12_U>-;i~k2lRQf%Ze;Ww!W&-W ztAZ!eFHzXBJSo-Z(MfW4U`IYw&lJ5bEZ>MwMTQAK;F<9D-4eVc&W-<#;<1FWAI>(r z>k*d{Dm%SdaB6)ouv{Wd;=rk{RDcp&9Yw5&rb6JZb_msqrw z%qI%A+*iBoR3|I`8(r0r@Z>f9104J%8vGvs8Y9Dhw9`2MxBer?ztPD553c>60U9SW z^MC9=x`L~y*sicixD_VhkbvQYabLMg%)Z6_5G(h`*7 zQW3CBvR^#$$i4CS@vHvPZ&*%uzWL{-{nv^l--(0ssQ~!lo`rP~3|25Q5{PgSu&8WV z9R^T9m_H$sp^}}Q56Lj}U21yL2GHJdj7VY8&u@V_c;Ep8TPX&(U!~zdE2&3G@n{jLmXnD{BtHfD#=(YxOKxnpsA_m^y$$!*`@d6#=f1y3z--8TfZS`5O zcXW6Y^umVMK|Uf~L$S+);k=4s%>Lmd{$>D8bOL>UmU!WJrC9%U0PZXdq!EZZ4-w!r zBIcgA3&jqkjq^V!JEs^?peW1ME4yCVwr$(CZQHi%m2KO$ZQHh8U7b!kolH+M^L2mj z-%U<(v(H}3uY3!vQTuNx@9u{$0N!p*!=IpDfgkY~)yEnkvBev`)M%LXHIR^d{`^Y- z%|b-LS(P@pVK+lQ0BDdOkRbN9g1S38S+scwlW367ZFXq6e=8t*Y5~4;jxF|r?RuMi z*J35QNFcsNecAO4kkw%>E+V;f*M&XLB|%Ptt9r3pqPMc9*z#tyi95PbnnaK`ACbVD z1H!j|AkWVI5`_hB`qw^0E;*VY7ufI`b6<@ya$7m!SzS(zq z^|%AS>yIM1il+d;;mQrK>#>@9-y9ifj_+>I2PK)UQDGiX*Hh@7uNNewnQgDE8u;Hh z1Z0pPAz|V_5ajrHyF2RN13$LcJyjfZhq|7Dp9yj>#*v_f-*Ua#TRTi#KMEi>x`+c{ zpB(`x7?j4qy&tjnQ+Nh{F)xKre>8u31ix+Tf0B-Viavj~<03*67HnB>Y=3_CLf8qj zyuJbTk}m!GWP(XBI5A6qLNExvrRqrlV;=3kZEG+p1&6RVYIkUWU5dZ8Rnd(D zLw+!L^y%#Zj*mef@PqZ3NvKFbUm^5MkYaAXscrfGMhO_!;sYcb0_a7$5PmJGz{B(X z{Vf!}FHlv+KI*<%b8T+c4!mfBuI~HR_{wqs?nT$)f6+xZw_#t)p>BI95YFrq*Rn{p zwr=7i>1|??hwP<|Jv8*lCYEtrm+OJlbUw34pLm}Q)S3IDeAAK=ZkuSU<3p9bIMB0= zcTqxm0{&8ud@kw*wL%Nhu0)9E^Ht2cNzUu#)zkJfwxw7yyTjs6QPxT|e7_5}ya$9V z!0bRHVoKQ+)ahc69M@f|2hkkus0~4*r%DgZwxkxgAD3{VzFQFjqc~N}qK!G8)aj!q z&@yvyN6#;$5!pvqPRmegyu?O?ZYrk#J+PGJgyYjocJ*P0it=BI)iDw8fhy)b2xfzD zQHBRUgnxD?5Bk8zdT>$?{bji7%~QppO@lCd8s`~FtP`cn@5p7w7xO8X$)?lUd_aSc zj9=IKY5V%8u9sjc99zgLCEGw7Pik;~Uu zu^@Z7^DDg7iCucs^ojVO$ne1DFw0?63!@yd>f^R}I5a4K<1hYpI_1>LVz_;BXXN*x zHTzydZyS%(L9Iphe=d=5__)Mgc*q$6W9bXtzIq7*4K!DG)H>~|61v}PLPT(*av_Wb z^X+_h@qF*f#&~OQ6duRxZ$5JtQnb$!PoJU*ul^X1_c@>*DO5T*QtMqTcEfmg|Aq7ink32XRm zl1*beuHWMsjv3{IyV`uG)BWU`$@a1H;1G_enF+tW0Z6%dAXmiR&NH+bsq00akF~ zE(s^yoK%3{_5j*OeW@YESQVFVW3jXv9?_O^LtsapvT ztC<@s5+y?IpOdjR!nh0V+o~F_OZD7P4u4ZOwO6G{3>sud4a!>D*6dEnLiLCWLXUI2 ztX71v>AYmqgd%s&0ARbY#`lcpv$FuNRtgpReU7Y0sz6RrkY$;tUk;XPbcM#_7R0Bm zU2+n5em0lQ_>GHqNB^F)h6==S=NoW>Nv}zdT)-3luj4PCrGTGIQ{W9RrV1J}y#XeZE4$j0?wO>Y$?sp<|Etv{6jC2RSrY%-!7DTxyo>qZ{aHG20$`kJ% z2YF--E8QCS>s#V^`9?N$u5&GP;b+AQsOiJ|A6-mX95(I!ZS3DYM-GRa&halkf(Uz3 z=0D;v&~}AqT53|e6^=N&NO$-g&^&M5a`c0L>=l--SOziMJsil6F5xdwOR2uRK@B_% zU&NRm{$j0!%$+n!G+ziOx_$bzoXlEd0PGh zs^qIUjvb4`Y$ACnPYNCpuzjhhP+(`1d`uTA+>Rk!8J{e5$`!}rW!Jx6opZ3bLOW7Y z{g~Xi=G3JJJsg>963_Q&ALr@Db}^$KIuNWc{meC&1V1zkBp;`U!GUk?j$DLV#4OTx z7>jqO8`>A9AJ(E(=B${RvGWZKR4;I)3NFMntwt_*J_!7W>Y&emkZkm5c@{7r|Lhn# zQswWXMRNKCwn zXvepIXbBRSn;wUdT7I$#8x&%Fc55en&Gpi z#hB>f-~p*Qo9r>_5sWHlB4=4?>BJK(@89!*AZh2f73}5kwQd(Xd^u0mmh^|7Oxi>@ zt=r}*$pubHh*0Brb%5<~b$Wn}`XU_K8Sxn-bn{(n6~;an4*!CzvrVvM z-lc~xP{L~%ZI|T$dpP9nRyta*JJ^BS@;afF9@ldmHNu%$Vpy3ywywjtB&spP_;6Fv zJtFDn$om&*pAmirhSQG?P%-=j99!y4;kqzhKzpD0*z-R_QVq+(ke!mvkn{2r({oUf zj+IcT8PPERmOgCs;PX+gFnyBKgU5D|pix8MOu9OZ)^tXCC&Z z%j>g>EhU~CABDY^oop<2RS2>Cb^fWj8 z{Z@mh0V%4&vX_!iR^sYto%fH%;K({(E7jFHmnTV6&~zeeF}jp1y8p_REPWjdV@d~I zkURUT3VDD(n0Yb+U9(YROMiVG7YU2fXm1XyL9|rspInA8;xL8`*({9tmmT^C z)(VpJXP^>twd4fQBtZmM5USddz70QFElr+!Vld(!bW3=k8@OL3nm?0gR;7A)ZH%m` zU;dNtD#(&Niz_u7K6&tujp%#*pj0B9@cKhqM8eT)d2kLBj1gEJiw<+61Z1ue7R%cN z&~M&meN68ThoOvAog8OHg8)8sWE6xDHU56FF0b3 zvw{~*z4p5=lWnHgiA3dzX?^4R-rp?qW1WD0hxbKCc`h@uwVVduU!l9yZxh@3x*CNL zgx%J2;0j)yyts2>XG`>)+cAJZ@0U>cK-Y295Ff9;mW6^_gqyD4lFJr~uZ0a#8Iz@G zsXq!t!iX5+#YXFb2;U(&h+&C$RabUu!l$4}E`Yx&c_^Kl-SD5s{(<&{vg*&r$W$HkRr73CIkwfVEPidyVv(HxKQ$UzAgxNquJLP z25Y)WDfkOR*vf=%U;VzZG|jfZLf7h3c;FPt$6%_$ifr8ai|SvB5T;My)%3YZx24aN5(RWooj z;ISSnhh2GJ+Dw;^Gozc!4qo2tmDjOqX;Y!@x+2xkpyjX8mMIH=SCS$W4ijbFbE`3O za&S5uS{CA(C{A)x!=o4s182Xq{Ol7geV_V&n6@5@F~i0_$hgVn;gqitnm!@CwNvb? zw`?WEE4W;RZ3CuAc72SxOt>fAuoHB1s$aW|gsl&?N>FX%Q)35=vPq0=%E4E<0@(yw zs;*u-a{6c~qw{msbq4ISKm4dCh~^vJW@tnT_68t%=fw~taN04v{dahD|8&f+P?+wJ z(@#^6YRrgaG|<*t>e3dhy9}>}-#p7#M^W`%@5cw4&Mg~8!qidUAbT8yZuz@xROBqt zWOoXtn{p&W=bmUh>EK4Y*_RhB@9eX8Z)4{Rw zUf!d35UUUj+A&qpA%DmOnh=>7Elrty7|oXUNXS!Bjqbv87s2Zg;9(E_918qd=#y6D|t7n!Vg z?XL<~fN)v+?9YlIfq-w9ImwTINv)`Af5C#c`GRLCCUq5!g{;*tR08OF3Dl+-0KhhlDP zjU>s@oSXZ>ouyE@{4?0~x^kY-Qd#KDRKimBU}vix@^zHcG`I{dSCz^$>CDJ@2Ko*t zzOXHiade^}R;Y&Int04{Dy$@U){4Bt=d4YLpU2VgmHW4;SyxpD3u)EH4I+>@hCw_M zInSgUZP#jmQlOx|xSZM-pJZ`u&yQ~2 zdSterLFVpz<;0_rFy#ZkRptF5X<0%QQ2;4Pp13QK^ zJdx3Pmkew93SK72i;2!Gn*@JdCj_+cts@EVF@#?( zt2FblzOahAJc1G7TFg0&lNvV`)6(*u9&VMBo1(?o&3!am&X%VpL#g)AU^R^!*R?Z_ zoOUSf7TWv+<(P4me2TNyWeAFmY7ku~r}4wxrSK)7^Gqnn!cH~5&783E4>giEj3OHxv)lfbMg)E7i+dMUuFW0 z80GJo+D9v-rqfUA2dyxU=81??~WV>T_%vt?Y!An#1e&u?3Ut?MO{DbqVT9# zD&16i_@;@u&l6re1n*__<)poPBMDZgqS=mv_ksR`)FVQlNH459&k7bb)kP=7F*Nhw zV8|!lVZY9*we%fF@iUFR&fCK3l4LZ|cg8*;wv{*3-qb6{?R@bv6rsEE z|6HDGUoT6niFWmD&JWA+zTfUbuIUwBtRLvU;|d?%FsvfZtC+&t+^bVs!qE`rd#vKb zfHOo5_)x2e`4zr6HSDW3zuI){<9J8ri5FEP^2lq$5-JI(TD9;$z+`RU{0g{*Vv9sR zB$-2_iNB)b2(@_(b((K!bGl?N1XT5|mh7|lwKeyA$;B6-~|d;hm@ znVo8v7>N@@78wF=t#`~Wj*G9eyl`E~j^?ZBopw|qp{5zxIbAs#LrTN zQV$KSye^lSR*re)zhmE>oa8+Y?#yjBLp5JWOvQTrHCH@X3YQ{|Q^lP+m^XpYI;5F~ z*Jf{Q+;ImvmRbsyV<}yR0NV4eX?7}lJ~+mA2R7-Hz?d?TM(EJYkigu!s1RlIr<-Ey ziIFdAbWW{Px#B%u#YjEDCw&rqqKh=DK;_W=R?Weo!R_kxyz%<;WNm+CXkg_ooAPLn z(7iZ#ykroSpbaw@opg7!KZNNAcEslwC7Lg_POQs>O4qbRb1e} z0WPs@_CGW~^;dcI!yllxQ^V)~EsbONe@NpP{=Zm}|CcoGx6Wp{Km#~m!2}-%5U>~r zkXP{AY?I@|j{|^@=R=Sn3z)BXB#`D4I#VcA1u2xUl~6p(b^1&0yXe^ckaM%$bgk`K z)%C*pFgf|r`7o)Ikux$YB!wQ*99U5x&qh!8mk3U7j=}Eb;RPuvBkX4y&&iatPke!wiXUV+#Zz8Q8DrsE^?u?=K%9aQp}6FESEH zDGvu6jSmidR-|B8jlu`HkrF4+&Z!@M{PPR)ZzC$8-_fCwkZ&kZ;y*j+ew+xvQ+|6H zJEFXN?nMy2fM(HN`&Zwhze-O1ds;_BL)_fl{&GYpVZ&_Oe-S|32<&744B1d(?)(M- zdcc7m^Tb|pP53B${K^mkKSpcqqvViJYJR?oZ(d<+~~Y@VP79;xtp~yqRp`j4l)yFy!%VB=F>x@+Ne!onxqF**6G&YUy_! zd%ryZxR{KFh6E^pD^PFOW!9i?5$jM#zb|KB&m=IY4^Oq3svnR)@Fv_I04Z0gSFIcz z8$hUi=*Qcq?MRQRk{%sENbSg<%iS1oq$S=p2$R-<9Ok??v>?=8NTFFAG=O*Kuaher zejPfdagZOlPgma|Wv3`+Tg=E${ZHJTs|_<+zt~hHJ}DWAWIR;}cE6}frrw+X4&*}Q z26a7wz7pi1j{HDJzw-FlI(p3AK8qmxdPqdTZ*L&q%>okl0Q!6rZD9iZE+JTNe_FnM zLqB(nekdn?B;S6z@SR;zQ+90ncD{cGV1x;@ZhilNOSp`{7Yo2ir@}1y3R3U-lBmPM z3bqpdY*YjXA`}avABoAeqNzcG$G;nj>Mghko@u5lvrP^bwE_;lfYF#B(RZXfEl>suEgevy{uo-?=hkDx7~;-OipohT?gYfUqQ zw1TxeGK-i-ume<*$PUvX_nv}0IfWY+oq$dg6m2CG%eU<$tFfIU^^9Qz>)VBcdUgJrX=mXCC&7OS=Z?Tnx#+1FS@`_# zhBk182l~$QKiBY{3m*pgcR8?uHx5DUMmanbR%eWfuzo;XN}kJ_Yi7I$7u#jHDl@`@ z#W6LPdUZ4oI^LZQ9o{RE<65$~>o(R3=Q^cW={%4vNB>pM3nkfs&QyZ$) z#u!Q+*ozQ}Pv}!U1-%WV^%P|6qmM^3I|O7Vp$K5`WCYYJ24 zIfIyF;%b+aCT!^X8t*D!Q`0i}Yf}o}G4ss3hD#mEc&#CKP9R&~vUvx`z1!(y|B4|D zt!-+I&SrF|+^$5U#F{mUX0+PDete7SF3`LXP zQbyKTmAJX2PI*r8EU=mzmPv^D(PS*fPE($Qj2mnVDq6H2*y8=kA17q0n4Ydz^4^hQ z2ox`e8|Uz{i(qiC^AERa_w@HXNjdK|328hNx4_msJ|RtHj{~hcHeMv%RE5N@x41QcKn15f{>; zN#D6n8@Y4n>e)yAMjVt3qF|kzYFmHN!82dN@=FQ!{ZQ;>93s(ui0-tCDoK-ofQ6Xn zRU^UjspCKfWU7UU%U{{8wZFJ9#_k?L4vKYrFN-(k9>B1zrj`)qyN z9#2C&y^zp$ollzwhqiqR5i$`*u;S1B2n~J*F551${>v|MahC}yBYn+~&P$GVb zyAet2e>f}(vXpVF!Nh6#`@u_*frFQX9{euxEPnG|R2P3YM(i*`DwM%3Z`<&rfDD(H z>~^}axuVzJbx7MWQ1V(?-k$9_m;?4GzNclOHop#MLM-ZLM>^frs-2|c$voGMKUSur zTeovICqf)BH@e2M==7ZIrxH=FHCDJSvI;OOpx`G&>s@GYX&tJslYAoLmMJ&%P-n;J z2LKDof(>-gC1lIE@i8UsC%orj_y@$-m@^;+U^!|LcXe!IAV%$H2}@y1O(0zfK5POn z$}N((#}4q7`=BF~RsiO5qe&0`SlxhX@G92@AB#!gYV^o^v7I0~uS*j{l844wA8p;f zT)`Y(p2{rheHVJ-^vF?Ewf~O3&spATE2{Kw%P={voglkVaRPd^r;orEIA4}1nFWm^ z&#n9uGTVaqQOS0y`4nn1Q+bprO!lFdLK30Ig&HN6Ij(l6F(NP2BN_CP$!1SKzg z0M`QWC`b0nQJ|($p47&%y-79m#@;kdUAn&;|DZDMTW^w|yFPn2Bt^UN^4?1k3$C2U z2M%di(3qM*3HjQzvD{`M_E~xDRryZe*B4)xj+kBXpYp4QzQMp=9Dgmz(UmcWH3q3@ z*`w98?NM^8+D(vBKRjwD3Se&>2hZ@FHv$SoQQ^tOrcxZPf5k*BH`4FH>tAJAHnG&F zalUzlsuH)6UHk>^~!rOEVZKj);bm zc=9?96iOj~7EDrqRev|FYS>6+GbCm+@${9kzorPdzi}@R##n)q9kxuj;0GI^yxuyw zS1~1SLuI$DIA}b6>c+X)At9&s%<6r7mcEY)k@uWAZ^_J!2&wHjkc&L0W7W;NV`TuV zI7b@dD#`sY?bB^T()a**{fwCT03~aLr0U3FyrF9pZZKYWZq|Ygw{2NTV^XlBSij2M zr7{P{OUjtIfT&6{%s)X4<9RHs+rD~w7Mwu89R0qmJM1st8CCGbta_b#QB<*f1xYyL z%qd)+5mA((YG=27#d(rxhb#7>-$~OYOljgfVT~QrAmUVg7U{z%K*9qAY1To!^E7iY zi-{tRuco3jlpUnYqOfQ7*9x~8508qGI4go>qMIDA->%}Ei`L>^{4QtcIX+~JXQlga zI13TYx8zn8Yab8ftp^dca>t%_S*|=1&fwW~9P?&TGq%9g_>29L+2K(l7T313zYUAh zJR)UXQ1FvrI9#ABeXPJ-q}>J}tHY<(uSzylkFcu!67Ygx$YmQj>SK`&oLxx0!y*}u zd-_ypb2@sYHdDt~o33rRZfhj5zuZ*WmBAltjIH9zvT#D4O6f}fCkAHHaL(~+%zw|d z!i~TR>I-fR>7V%1wUAI=B|Go^4KHz0Mim~&UDF|Vt`DoVT~!lm(ouSWJYkEXn)JZM zPyH&Z{JrTv+%&yzl5k~{QK0xVg$^w|lk*XUCuD+a^GF#4NoyGJ6z}=uzz%_E${aTr zZO(_+eMwP}cS;w0d>MfYbAV9kbPmm9q5`Iy&4AJzZ!+me&LLIG!qb`}M%R1l0Jsvd z=9y>>N@P>4Hg&2K(#H%}!6yqbOZV0hH>Dz6)T-MYm;IVau2F60jurS|%7rnL02@SE zOolray87x(7%e#nMr1GK#+u$+BG&x1nFsR^d)fFCp`WZ;9?O41ZtUuNP3IEI$dLv= z^^u(vN5!7H+qQd1Mb9-YQgNiut-WD3&o+wEC_=SWr4qM`5xFU6=18_eE3q~wnS(Yl zpxXB)gWO6>(rGL>dB%k)5P2>K#Ak6DB=L69^uBta`62J~STtG_S$l*CS+s#DTo+EN zri;95WccdAZmx&Rj6O`$aB?%ryZZ^J845)f-LJddDdp$4;mdPih21lEzbOYu^=JDZV2zyGAb_0ak?&C z98SR;G{M$(YdU@A?83MPySP~)P(O6A8BLvjen&KC4;N_3CKw^< z1?7}QhsMWXQKhVN7*afe1f?PIrn36tVrl3JWsK6-k#g%fEAIukJ#&cDEn*`yO~%N+ zc;3~Xn9=wV>~aL8<*us>(q0_6`qqTY@3}_y-9?ssw`s~F+`$)D{);K`{uQ)4KdV(5 z?wq*Z)r2HwKhWq=6TW%$+ZLQ9k5htUIxnVO*P(Qmp^c4uvZE7q(W|&ldm_9nF$tsCM~B@D%LE4q z#fHiwWy)VrBEN8gGS&F|-FZl7nRsSCo~7=uG>TOhAq@|=7WNCUNU2rDlu$8Lsr#7~ zsh+!kJ=Lt62jW>r8BEibVhQG0w~d4Si!}_ja-2mo3(|gH<|Ss$6(*2TxKz2nB_$Hh z%8WMVh4%de-Ps5A%B-%pb-Vktn{d7JDE-n(7mQA_wOe7zFHz2avpKbE*|nS}tFpf! z^3{GFZ<*i4c+%lsC?mcP4D^RbYy)5B8cFF8sP>gjqfHQqDm9g9%k~cX%fO(! z^ZlfusfR>V@+n7oWs$3k-wiJ_$*q9C;DLH3JIi-@!Do-imd5{fybHRu?ojxKT^fxx zNOESIfKQod6kJaRpFjVgTV%>_PXmq})IVsY0b9)k_*awU!-t4jF?TwSW zv*DP7DNs+{GI+$twq9q+{;)U(hwfSN;x=ZNo2GTBIj?kgeP-|&8MLHo_!AbUHndp3 z4La##%p4<^O;U=S2$xf6>?)qq-}4vMUd5O*M25M(ApFFhUEOhgNzONiADVyO@t$Hl z`Arwl)OSj_Ziu8a!$lBs*r+VrCx9u6xb5UOveTWtpXb7@^VCj#2;s9Ta(pYdPs>lw z2vG}OJ7g8{GOQd>c87h}`ucJ%H~=budJo1Q#4=>O>3cDEvgz{An%%v{kgxz7piEJ0 zEJ;#!E}LW!;xZ9wa-`DkYQ?+oL6W$8%0cp^&W4(17Cg-0ld3*6I2U#^0 zKOioC5lzurJsG+}-#60ocu=#r(;GiOCsET*8#;eWaC7pBw>m?LQ~p!mzebK3Ms;BY z>9~S#r*53xw=Vn2(ga}kQI&{F;Kwu@OZ*m8u|i{C$E1B4JzRbLT9ElFP~6QtD{Bzu zjM-Y{u@CYUQH!{9Z{mX*aVu0>q>p>hH2if>m3hEw)t+_4bga3#VP8c-?yTFvnaz&jKS|<6lslr#nNo5j%}7>s0q3k-yeF=^L#N# zYg5v*XvpH`{8=43@ac^(A|sIo_1yUCJ3i7g^f@H64?t_|s|xRzrt2kYVv0$fzjmL)*m}R2n5O2FuaiU|jQ`TbEck3sxxlI7 zF#@-Dx}MoNb_QQ+JZcyp&ChJLOKqMx0IOXbTlHy5uxVEyB#)W1dJTof9I89{P&>O^ zO5;66ko<@5DlpKs@2aBdNcwQFKE@oU?6g4|-zI$>n3;92S+s^zIaE}PXv{S2mGR=$ zjKvlptJ5=OTj#2S|2#gMKh#?QT0yNqU=<7 z!NtP}qyH)ou?ajBV=^EDpwRN*L5ZO5>{c3o=fVn>uR7G!8$UUG=;n+97*p~|+A^JK zx2M3vkUveld}FiBMNyM+&pD7bB!~N;TjfnO+s)N%AaZ#TOf|q0q?Xmb19{7VJ=a9B zeaqH9kQ#orkIO9py7j{YgzUih(`^*MvAn+D*&XpSU$0$nh*?tS?u z%7ZgR>^V4nvlCeTjS+GUq;{4qNp~c+9(s-u)-6xl@HuB)gr*ur9H^)qTu|*!x*RRdA3+DzifU-h2RB$$WC6St_X;MMGXAnDM?oMRO3jM3(lCu9Sf4)CDVMg1G}J-Oh#JOQkNN0ByXXVQ~LUKT2wNy?C+(v<-7sy8@@U1XwA26S|F?klUm7}*p$r;LggH zB*Ch5y_l-2KypiLSF_`ytn~#lPWNmI%Gp@cani@3lwC78Xd`!S-RE%A@txH_jwSu} z#Mm?xrRmq{4USf~)Nrik%tmC3k}DhA-foq<)_t$#770hC=esDC)xC=!&&SsuE#xLD zo(rp3SEapb3OZ~QjZVAa9IiZ(y3(^ps`2AOE_J9;(SL)viyGojD~{B0I}m%Xv(j)s zj7z~9Y#3@jq>xarX5Q~6Vm#@u&Pdo99xr<%)7Os->bqW%^Y8URFPK*ywntQkEQj~4 zF-;Pe0;O|O7F0{EyI8w7og8hw-}XR?bcsE0q>3!*O(Q*IWrq~6Gf115plmMB1SH@q z8SitfP^7r{K?9QZ`=)F{uF!`KO|weSr$Xh^mK3o0lUh5?dIH4~PO3?&F6z!NHG`Eq zZZc5SF+xosnVoAk$P*0qSv=v$MF)DGUH;yDqTTNk%Z;dxNlf1d5vAmF2 zCLatWDFF<0m#(w)3Wq6?_WyR|!wZ5CTDsZ`MQhe>_|~SXL#K}*@42IMh^st40y-zh z_aGkGcGY)22Nqy*ijvOsQM=nB=j>rp(M)o-_%dgbz~b&-AzFIHBCe#cFXpQ|sbSBO z-&$+hz4S(RoU^kG$@{?7A#0$j{CqP3R95`cI~8)8=-)RVgfXRvWNB!+Pq)^D&4W>` znIRE&fvLaDYbr=ka1*nqGB>++UMtMlEupl^ugW0g>CYcGARUBt020brD|knCJNYO? zL>XdlfO{xMM8d+wz|e!ql;d0}NKs=^%VPPh=*9}Jy+q&wvh!EY|wR@ zm9EPnxlt3`Ozsi;3gajw)3}Y(-)Hl;&n4~kItVnUFR~$$9Lpgf2RUxb*eMl@N>%gy z!15UCX6RD%r_}ZsGYcsaAZC1Y@J~$@z@NMo*jrJ*FC3rAt5KnJ^%eSrJNH+H{6Dib zCU&O(k*z7Y+Zp50${JWGI$7h<%HYw{{Z`yW%pDw^@YvXY-8mxWR!+tazo(VHld+Jo zp{>#H_5Z5C;W09@vixrqw<%3c#SJkOpA*$bLj^@K?;fjPV~n0yDzy0Wbg)ze*a+D! zdM(+;CCS6Z3n%qjJ02rT>ZH>6+?h(nhgP?vdD+}H!?Y8fl$chRfxvRcP@G8f}DS zd)Qm|bW{*f%T+-h&~A+i@c3c98mWsE_0a=*3g!06>QKed#Q>;GtBj`l9H}T`VGEMS zZTJFzWKcc<47UYR00lf`pF!5WZiRqRgnEPMTxtPet&jlC;j;o94_u-7lO=0S!IiWm zhY0lbMWD36uWJDd@lW+@iIal|>G}bv${_~TbkwW~GlOsCazFxhp_BSC5rwgMo!(0wk5+Ik6%kR(#&N7`*d%ym09-eO* zaQy7akv(2B;t7Oee>Ki2`m##ikrG{_@=(6yn4TUU==#L`h+-MDMSwtbqeh^zmvEG( z7uTZWnaz-LNM}SsJel+u%Os}*NLSFIr8V=m#O!rt^sGhBaMxjXzNSYE1Y5nV+eA9%&X&cA#S zzH_&w&eWLxNG#0RG2qIEjJ4eSn&!-Hef~+;>%SvOAs)QwBlzP(1TDmip9upR+Qg2j zTiw~h(7>UQuc4r@y**-jG1mF_!X@EHN!ifQ>Q^QeSYuhYNpk@XdKAFVBHTAWiCEGi z?s`qlfg^-#XCUqg3gFZon;j(p;IW7#uxcGI^gY=n)&W-XJ$q$KlZIv2y*;$NMfQ2I z&FI;k>z(0ah0Q61f-B}d<_Q)eM+gZ6)rAYl%=ux)8x`sLm9gsjkS@+5iK+rLs!Vv= zmb{t8!RODnfQ9zzKU>Qb?6!R*MP*$}p;sSGCwAZ*PA4i;y21uSC#n@_rqnBHP*?B$ zv8mP;>&z1x?Zb44hYYv(ug9%^vCnWe<^g$fKZ3QqIGQd6{M3lDn`u-x@gqmvI@=hjaP;V`x2uVnBoi zrlp}_4&r=)S=17bFHb|;wy_?cA4S`-aZw+ryGo{1&$se$lMnn#KS&EN92LaXopLa} zgRo#BIq6w47KWY28Ig^m`=ck@4NgV zNFuIc^rTkn;afXKitcc9%mPV9j!W5g?ruY-^V%SZUR-TP+cAc(7QizXCL@Ba8~VFX zc4y-DQ%NRglJw&ao}c%duk0|(IkDzbESN}{^n&fQTVvMIb5L2izGPQ|uTOU)lRWmQ z_Uvq5{hSmGNx1r-7*X|~p>1<{W6B7zoHSJ$e5S=nbA^3=7EI}pl?N}4MqRiX285=U zz1J;Su(g{3IM%>Dqvnnj-E95Aqg$+udxO($K&OsG4v>-KUUiwUiz$&HHjAQvl|FZ+yVb6#%jI8P)eDd@-IU=Nq)f=v1z3Oqu#Y5NwT2NO{`xJk!byc~Fu z=v!hQNm>&eWv7Etys{#1Yi-m|#RvW|4?OQ^gBm&nKu#|-XD1}~nTj9r9DBKU})*-sGQ4!w%McFyvrFn=mV z!eWphn+8$5vs09wX56w)-Gs~d68erH3PCuKQ$o_orXxw3{g7QW<(9E9N2LF4`8t1Y z(1tQ+Rf95L8L@ycXP<#GM+7aU!b(eF_E1Z?if#NcrR3PPdTZX>EP6+YkJcnuTNUN2 zwuOOIrRM{J4V{y3vS;EZa)fIEPuw;Bxs$&C~d)4S##twZ#WDh6S%S$+&GA|Set4Y z2PO+@bUBGt;Pl~x#A&(}vUE#<*9(!PIEAK{Zx_m9M4OZ{uK@3seD5lA*TsW={|WCs zBl*r;$M|k1zV6Lwzvo4?y|O)Y_j37wyG8m|E3>I;lo6x8!#ePd8C(R913T z)_Yo_;&C$0lzW=bZjumc7ugt=5LmfJUrMVDTA4BxketPhpS|QIYD;TE$f~X~7t%iQ zeX1bsQ}Hb|Dw^p*);=4!HxVeZ?V554hN2wA_S)-)o-(yuZDQu!z@W2+Noy`<#Y}&% z>s!I2VUc?OVy%Ib(d1#~+t zjAmikF4$ttTBqYjv97c@6N>tGcM9fSQ)CPvy&ra{IeSY8sXi_mPY?r5Bm=#TP^qXW z0&j3RTOLs{Ei@(-g)B1yEyN>DYEBne;&Za{GSii?y?eU?h(cTZ#+C7P_p)@~m4{hMjE2URqP`Sc5ae|3{^8*G(*ZT7NDUmLP9447S|)k5k_q zTuEOwIR{hL$bSC4j1+&#&?qPMn~a{5M4=t8j(b^nUN5k&4)H=G!&guQNW`KO-LPnS zjE#H`@{rp*IR{F}yYz^sQxLS|oNL;$Z1voliuY+WYv7wmjpI z7xqZ0!HD8)u#KdKvXhdDI4V7$Nr5ghDN?}$8T{b# z{F}CeD{xdUC!mO&=FF*UdI2&cV2y!@TU08%zlHSXtdIhde*YksOx&}K=wFSJ{2%6f z*D&~iSuAF>z8b^FrMltR7-Yt#$g%}^^n6`;JpMsGV7ohZ#l;7YuNOel8n{^5^oYV4 zOIB50@a5a@rP^m|wT`MTtX9Fxjnd{L{92Uqf#sdQo5oQrrB?`xNB(nF0Up$s&^%q= zZ9fa&cX#l1I}j<_dLF76fY8X%#jt3RYVtr)!aOwqf+rD}erq75lB0OsN^$%#(l4|j ziU5ZY$-{zFU&x&ek3f<$C2Mxs(m5)n|IyfWM>Vx)vt{{%yo8CPN zy&ZQ4$vRQOp{1>Td6U4OwCOl!vvGBGyBF%B)5)u_)PKs^UZOJ{k$URX_p`sGAd=53 zQ1TL2*$SkLAW+>)Uz!Hi_ry_;v?ixWVH*A!pOAw0qr&K4Rv{TJOqVTAbTU@B`O+I8 zZ6|V@qGW?nQ4)5X&(j_D9_^}Z?b^zBaz#Q#q@JaAm$tj)`9-|kj=ueQg75w(+OSA=iP=&ygQg58O-0FqJ^k#FWzommqOy{Ye$8-LrC?%08ESB)5}6dK z_pvlAf}j!O9{{-a3+>k zq|pi%ZC?j}!SQQ0yyI(`xcp$24lBHPZ2jFx@F?`m3yCt@PzUU^k*FDXsV2@gzE2QO zQyKUjI`Eie2WE7YcXqw#>_yGwcD~Dzw`3mc9Iu;T*Y!Wfp$ZR{)IgZI z#k&EubYRXl%KK^7&QrbgYOC0<^odGkH*Mv^dCyP~DYPqGNb6I6CPlEDl87i?I?@b# z82wjP}!Qd(m1Y!UlxZ6i~`r*BZK+ZS}??D7~)*cRcCrA{5=nL@$ z_*_^R-UqH?g})pX9OfMkgF{r%VZq)JUI34SSx5Y|RZ>${Ln^BRnm@WA1P7S_^bP_u z(NR}b*HQ(REvl&_5UQFuz~Wr6_kUJ8gn5L7;JpEU=n)VOFhjJ1sgtrEjefCVsgYeFO*0=U*tF~NHhJc8hGfLH!}Fu|UF zTv}@XL|B1cR{n>ts%ru#iT@K{RntcN?SbKO&KHB{wFF|f9xYT|>^eg$Vc}smOky&f zKv>MxKw#c394Wi8uPjBON6(LCj4N5LxCXpWyRgQSI?y^C(kJ25;Zvk>NnAAhbYF+Y zVD!lrJXYiM8LVDbi?#UcEN@(Nb=D!@tm*kUfCG0qZZ(;kyDO-~_Bm7uR8 z=~FUIxSQI;4hnU3rWk_b5Hhg7dbwmGec4J^zhq=-ajCLxaLQ~IyE#1xb z%Cr{&$#2>XAB2cx&KS8_TwA+6m}X@&U~5w<>aV0LLzh}q@Bs~+T(6AGZ6Ot9l*g!E zaXNohC8ldBlIXYHdTgh%#f@8i$R%`pcHwLO>-3$&aQX0lvV73-xwzE5rCsVG?Z?K9 z^y`uk$5&0$FLJ1dj`2cmv*>b8i#i%-_bp;L)P#X1oX1GxH5JZP%zp0C+y_P)G*2lB zSP8O2U8u|z^|E&yC?Ej~3!4eSV;twqIUq?gAPexR++3X!R?xo_&Xxs=AS)Zl2uX8E z=vXGDRO2jiM;*91LB)P2414g84P@S(|e(3}C0oiD)^8g$8f%EK{G1F2vb8 zHy6>&#;IeHoN~{Kkc*zQl7I?t=Cg5{-uKT%BMf;#CtZ#~t=qsBVs)KtoK_Lj5D$Vr z8`RgG8B}!A*Pv&dh1bHVxZG5%_?#2YsW{7g$Kpu~f9k~ccdtG5A1bToV7<+4^B>4z z#K6v)cv5W8UR;#Pg97YURgB*CgRQkl?bWSS+9guaZr|5Kyq@%3n;fqzr0#;3KQxJ7 zVA-x?BemC`R&e-v>9bROvA#wj&7Xx%pU}?Zt>Liw^lgx{JH5c!yVRm^sE3BSgE2y5 z6{TbihEuSU<`=zC{G_5sZbdEwWw|e=DM(ne)_7+_^+WKk=R15Kqwgp}Ebb z1X*Yr3wKe5b16|MUIi0 z!>ptb^665=2MS{|4+|zg1ilBv_4f|97fIEwK;P8o7ZiUzteh{KVNA2zm|;y*Z<^tJ z0|;K|6(8xcp%VUvbMf(6#hA--k)T3HPh^FHmOvj?(34j|_T|I{`BbbSb}uLLrzir% zBhOBU>T=Hk2MVi)qiI@${ng50%_TDmwlWMIa7vz?;)jt3zsu;yHnrB)83w4-`3bmW z^(QqA)y{)muJ;EvQFBEk_Nx6_XLK=>o<|PL31Q;}r_|aYnA;hFX%Al|H9qV~3W-+A z7uVMa(?3l5%3Gkm6e$VAI1d}#?+-iann;dkLt)Gi=>Eb2v}Z}PyAy25imX^bU-AT_ zcEZ%S$+1tIv5WD__nmoL?)mTrt@%A*#VuvVyl5_^P*wUlI?fc^v5LkdsI#W(8x*_^ zVWJvZ4q28j5qiikH+~7>{LFpsD12D})d%_(6ZOp;QJm>$!*A6>x{p-QUej+)`j`9CQJ#xhw0-@0m;dLGbw6QZ;iJn z0?+VhX_j!ZwigejBnhpW8HFMryo(ki=`?Msu9vD5HN}y#kD}9_OqU5ll{H(^y2SVBw6Zb|1M@h{$*C#$qw%WQLzm2 z#*-i}fL2Rg8*&k%Vo!+1|B+X51gg~_8bAW7?Sg}eK(!`dX!o;~PcTsW83_F>nE;l0 zT1d0gCR*C6+N!38s%FL}CP*V~RSk6$Bkj}bTE?f<_5T|az|%j*2$~vy8zaaSSp{G) z!q>K*{ysh)v&Onxu2iGK)ly*Yf^#LaqACpFtT>d5G+7ulW+LPj%ag`@-8nB;%z_9R zOV4Sn@~FI)9_ndOx|5a;3SAgX=`b_%@=W^dawm2+W;Jg3%;)|07eA-u*2m;?dzN(h zG|Gt@>03B;NHp6HE*Y)e$4s((sx7pw$3JB$uysK-Tq8&;lCg#j#e~zfKqHs+rkjdGgB zi`R4^w3&yKlR=SNdxAGE;QuP-&(XMD35aQc4;+AePf8}X80|yXNo<(=nlh^ zajLt*4Ewb%Lsi&S$;|V~K}CGY%qGjP*BFJ|O}NVR=yAZ*bO=jUQk6T;G3Jj6cW;dg zkKb_TDrFPP8wOrITPf>4vt3S%9hcjS-(EyY4<>Ri$T%_F?1D${sSDg&-#dG(f+@r} z^ncN-Y}q`zXfDufF&jsItx1BLL1l`s2N$hS-R0soaawL#SbTt8{-cA{7S&hh2Eq2ua95+^=lVS^avx80GiEpT2o6)`!tuFoauQpu73e52Q!8M literal 0 HcmV?d00001 From 367e97b77ebe56bfcce663606fbd0cc3ce7fa49c Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:51:35 +0200 Subject: [PATCH 064/159] newest file --- ...pdf => 2026-05-29-cantina-competition.pdf} | Bin 958486 -> 955171 bytes 1 file changed, 0 insertions(+), 0 deletions(-) rename audits/{2026-05-29-midnight-core-competition.pdf => 2026-05-29-cantina-competition.pdf} (91%) diff --git a/audits/2026-05-29-midnight-core-competition.pdf b/audits/2026-05-29-cantina-competition.pdf similarity index 91% rename from audits/2026-05-29-midnight-core-competition.pdf rename to audits/2026-05-29-cantina-competition.pdf index b0ad4ce7a392749c2a66d005b2d44fa778378e0b..ef5622e48ae54c9c2d8803d39336532f3370d997 100644 GIT binary patch delta 77152 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

    n^>MDM#Nj8@3vHh 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 KODIWx`o94A&z_+G From 9c8831f26671c67d77d23039946cf9990995a7ac Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:18:34 +0200 Subject: [PATCH 065/159] Add files via upload Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- .../2026-05-19-midnight-core-stermi-audit.pdf | Bin 0 -> 184804 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/2026-05-19-midnight-core-stermi-audit.pdf diff --git a/audits/2026-05-19-midnight-core-stermi-audit.pdf b/audits/2026-05-19-midnight-core-stermi-audit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f7ff34a52342e7000793bc52e79a3ba6be7a651e GIT binary patch literal 184804 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�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 z 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�*7ptNcll2lN;g$9*SUAVec>dX<-Ff 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

    S6PtHR8ka)K3V#5 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 Y Date: Mon, 10 Aug 2026 16:52:40 +0200 Subject: [PATCH 066/159] Rename 2026-05-19-midnight-core-stermi-audit.pdf to 2026-05-19-stermi.pdf Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- ...-core-stermi-audit.pdf => 2026-05-19-stermi.pdf} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename audits/{2026-05-19-midnight-core-stermi-audit.pdf => 2026-05-19-stermi.pdf} (100%) diff --git a/audits/2026-05-19-midnight-core-stermi-audit.pdf b/audits/2026-05-19-stermi.pdf similarity index 100% rename from audits/2026-05-19-midnight-core-stermi-audit.pdf rename to audits/2026-05-19-stermi.pdf From 73755a4a93e396edf72c428ba127321109010f72 Mon Sep 17 00:00:00 2001 From: peyha Date: Tue, 11 Aug 2026 11:19:19 +0200 Subject: [PATCH 067/159] refactor: interface folder --- .../{ => interfaces}/IBlueFallbackRolling.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/periphery/blue-fallback-rolling/{ => interfaces}/IBlueFallbackRolling.sol (87%) diff --git a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol similarity index 87% rename from src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol rename to src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index af2b9ed48..d15e5aac6 100644 --- a/src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -2,9 +2,9 @@ // Copyright (c) 2026 Morpho Association pragma solidity >=0.5.0; -import {IMorphoSupplyCollateralCallback} from "../../../lib/morpho-blue/src/interfaces/IMorphoCallbacks.sol"; -import {MarketParams} from "../../../lib/morpho-blue/src/interfaces/IMorpho.sol"; -import {Market} from "../../interfaces/IMidnight.sol"; +import {IMorphoSupplyCollateralCallback} from "../../../../lib/morpho-blue/src/interfaces/IMorphoCallbacks.sol"; +import {MarketParams} from "../../../../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {Market} from "../../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// From 79a30b81456b3ab0a150a73ba121ac3d88008ff4 Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 12 Aug 2026 10:13:42 +0200 Subject: [PATCH 068/159] fix: decreasing incentive --- .../BlueFallbackRolling.sol | 9 ++++-- test/BlueFallbackRollingTest.sol | 31 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 264779548..b109895ae 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -9,7 +9,7 @@ import {WAD} from "../../libraries/ConstantsLib.sol"; import {IdLib} from "../../libraries/IdLib.sol"; import {SafeTransferLib} from "../../libraries/SafeTransferLib.sol"; import {UtilsLib} from "../../libraries/UtilsLib.sol"; -import {IBlueFallbackRolling} from "./IBlueFallbackRolling.sol"; +import {IBlueFallbackRolling} from "./interfaces/IBlueFallbackRolling.sol"; import {SafeApproveLib} from "../libraries/SafeApproveLib.sol"; /// @dev Users must authorize this contract on both Midnight and Blue before their debt can be rolled. @@ -79,8 +79,11 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); // Round against the roller. - uint256 incentiveFactor = incentiveAtStart - + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); + uint256 incentiveFactor = incentiveAtEnd >= incentiveAtStart + ? incentiveAtStart + + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start) + : incentiveAtStart + - UtilsLib.mulDivUp(incentiveAtStart - incentiveAtEnd, block.timestamp - start, end - start); uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index f032b66c9..cec4a3cd1 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -7,7 +7,7 @@ import {MarketParamsLib} from "../lib/morpho-blue/src/libraries/MarketParamsLib. import {Market, CollateralParams} from "../src/interfaces/IMidnight.sol"; import {WAD} from "../src/libraries/ConstantsLib.sol"; import {BlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol"; -import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/IBlueFallbackRolling.sol"; +import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol"; import {BaseTest, LLTV, LIQUIDATION_CURSOR} from "./BaseTest.sol"; contract BlueFallbackRollingTest is BaseTest { @@ -187,7 +187,34 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } - /// @dev The auction can be configured to end after the Midnight maturity. + function testRollPaysTheAuctionedIncentiveWhenDecreasing(uint256 elapsed) public { + elapsed = bound(elapsed, 0, end - start); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_END, + INCENTIVE_AT_START, + true + ); + vm.warp(start + elapsed); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_END, INCENTIVE_AT_START, DEBT + ); + + uint256 duration = end - start; + uint256 decrease = (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed; + + uint256 expected = INCENTIVE_AT_END - (decrease + duration - 1) / duration; + assertEq(loanToken.balanceOf(keeper), DEBT * expected / WAD); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + function testRollPaysTheAuctionedIncentiveWhenTheAuctionEndsAfterMaturity() public { uint64 lateEnd = uint64(midnightMarket.maturity) + 1 days; vm.prank(borrower); From f89c785bc7205fe867995a55bd2868fd8fe0658e Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 12 Aug 2026 15:51:20 +0200 Subject: [PATCH 069/159] test: coverage --- test/BlueFallbackRollingTest.sol | 102 ++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 23 deletions(-) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index cec4a3cd1..7e6610cac 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -2,6 +2,7 @@ // Copyright (c) 2026 Morpho Association pragma solidity ^0.8.0; +import {stdError} from "../lib/forge-std/src/Test.sol"; import {IMorpho, Id, MarketParams} from "../lib/morpho-blue/src/interfaces/IMorpho.sol"; import {MarketParamsLib} from "../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; import {Market, CollateralParams} from "../src/interfaces/IMidnight.sol"; @@ -31,7 +32,7 @@ contract BlueFallbackRollingTest is BaseTest { function setUp() public override { super.setUp(); start = uint64(vm.getBlockTimestamp()); - // Deliberately different from the Midnight maturity: the auction period is independent of it. + end = start + 12 hours; blue = IMorpho(deployCode("Morpho.sol", abi.encode(address(this)))); @@ -251,27 +252,6 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } - /// @dev Measures the gas of a full roll: supplyCollateral on Blue, borrow on Blue, repay and - /// withdrawCollateral on Midnight, plus the incentive transfer. Rolls at `end` so the incentive is maximal. - function testGasFullRoll() public { - vm.warp(end); - - // Copy the params to memory beforehand so the gasleft() window only covers the roll itself. - Market memory _midnightMarket = midnightMarket; - MarketParams memory _blueMarketParams = blueMarketParams; - - vm.prank(keeper); - uint256 gasBefore = gasleft(); - fallbackContract.roll( - _midnightMarket, _blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT - ); - uint256 gasUsed = gasBefore - gasleft(); - - emit log_named_uint("Gas: full roll", gasUsed); - - assertEq(midnight.debt(toId(midnightMarket), borrower), 0); - } - function testCannotRollBeforeStart() public { uint64 futureStart = uint64(vm.getBlockTimestamp() + 1); vm.prank(borrower); @@ -489,7 +469,83 @@ contract BlueFallbackRollingTest is BaseTest { assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE))); } - /// @dev The incentive `elapsed` seconds into the auction, interpolated between the two configured bounds. + function testSetConfigEmitsSetConfig() public { + vm.expectEmit(address(fallbackContract)); + emit IBlueFallbackRolling.SetConfig( + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + false + ); + + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + false + ); + } + + function testRollEmitsRoll() public { + uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + vm.warp(end); + + vm.expectEmit(address(fallbackContract)); + emit IBlueFallbackRolling.Roll( + keeper, + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + DEBT, + collateralAssets, + DEBT * INCENTIVE_AT_END / WAD + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + ); + } + + function testRollTransfersNoIncentiveWhenTheIncentiveIsZero(uint256 elapsed) public { + elapsed = bound(elapsed, 0, end - start); + vm.prank(borrower); + fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, 0, 0, true); + vm.warp(start + elapsed); + + vm.prank(keeper); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, end, 0, 0, DEBT); + + assertEq(loanToken.balanceOf(keeper), 0); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + + /// @dev Rolling with zero assets reverts in Blue's supply collateral. + function testRollRevertsForZeroAssets() public { + vm.expectRevert(bytes("zero assets")); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, 0 + ); + } + + function testRollRevertsForAssetsGreaterThanDebt() public { + vm.expectRevert(stdError.arithmeticError); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + 1 + ); + } + function expectedIncentive(uint256 elapsed) internal view returns (uint256) { uint256 duration = end - start; return INCENTIVE_AT_START + (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed / duration; From 1e52be2a05fb151374725fa473b2540c35a8e0d4 Mon Sep 17 00:00:00 2001 From: peyha Date: Tue, 11 Aug 2026 15:28:51 +0200 Subject: [PATCH 070/159] test: midnight coverage --- test/FlashLoanTest.sol | 52 +++++++++++++++++++++++++++++++++++++ test/LiquidationTest.sol | 20 +++++++++++++- test/OtherFunctionsTest.sol | 23 ++++++++++++++++ test/SettersTest.sol | 35 +++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/test/FlashLoanTest.sol b/test/FlashLoanTest.sol index be0963b99..106b90ec7 100644 --- a/test/FlashLoanTest.sol +++ b/test/FlashLoanTest.sol @@ -8,6 +8,7 @@ import {SafeTransferLib} from "../src/libraries/SafeTransferLib.sol"; import {IFlashLoanCallback} from "../src/interfaces/ICallbacks.sol"; import {CALLBACK_SUCCESS} from "../src/libraries/ConstantsLib.sol"; import {EventsLib} from "../src/libraries/EventsLib.sol"; +import {IMidnight} from "../src/interfaces/IMidnight.sol"; contract FlashLoanTest is BaseTest, IFlashLoanCallback { address[] internal recordedTokens; @@ -78,6 +79,51 @@ contract FlashLoanTest is BaseTest, IFlashLoanCallback { midnight.flashLoan(tokens, amounts, address(this), data); } + function testFlashLoanInconsistentInput(uint256 amount0, uint256 amount1, bytes memory data) public { + address[] memory tokens = new address[](2); + tokens[0] = address(loanToken); + tokens[1] = address(collateralToken1); + uint256[] memory amounts = new uint256[](3); + amounts[0] = amount0; + amounts[1] = amount1; + + vm.expectRevert(IMidnight.InconsistentInput.selector); + midnight.flashLoan(tokens, amounts, address(this), data); + + // Also revert the other way around: more tokens than amounts. + address[] memory tokens2 = new address[](3); + tokens2[0] = address(loanToken); + tokens2[1] = address(collateralToken1); + tokens2[2] = address(collateralToken2); + uint256[] memory amounts2 = new uint256[](2); + amounts2[0] = amount0; + amounts2[1] = amount1; + + vm.expectRevert(IMidnight.InconsistentInput.selector); + midnight.flashLoan(tokens2, amounts2, address(this), data); + } + + function testFlashLoanWrongCallbackReturnValue(uint256 amount0, uint256 amount1, bytes memory data) public { + amount0 = bound(amount0, 1, type(uint256).max); + amount1 = bound(amount1, 1, type(uint256).max); + + address[] memory tokens = new address[](2); + tokens[0] = address(loanToken); + tokens[1] = address(collateralToken1); + uint256[] memory amounts = new uint256[](2); + amounts[0] = amount0; + amounts[1] = amount1; + + for (uint256 i = 0; i < tokens.length; i++) { + deal(tokens[i], address(midnight), amounts[i]); + } + + address callback = address(new InvalidFlashLoanCallback()); + + vm.expectRevert(IMidnight.WrongFlashLoanCallbackReturnValue.selector); + midnight.flashLoan(tokens, amounts, callback, data); + } + function onFlashLoan(address caller, address[] memory tokens, uint256[] memory amounts, bytes memory data) external returns (bytes32) @@ -94,3 +140,9 @@ contract FlashLoanTest is BaseTest, IFlashLoanCallback { return CALLBACK_SUCCESS; } } + +contract InvalidFlashLoanCallback is IFlashLoanCallback { + function onFlashLoan(address, address[] memory, uint256[] memory, bytes memory) external pure returns (bytes32) { + return bytes32(0); + } +} diff --git a/test/LiquidationTest.sol b/test/LiquidationTest.sol index 80d2d30e2..238ea307b 100644 --- a/test/LiquidationTest.sol +++ b/test/LiquidationTest.sol @@ -9,7 +9,7 @@ import { MAX_CONTINUOUS_FEE, CALLBACK_SUCCESS } from "../src/libraries/ConstantsLib.sol"; -import {IMidnight, Market, CollateralParams} from "../src/interfaces/IMidnight.sol"; +import {IMidnight, Market, CollateralParams, Offer} from "../src/interfaces/IMidnight.sol"; import {IdLib} from "../src/libraries/IdLib.sol"; import {IOracle} from "../src/interfaces/IOracle.sol"; import {UtilsLib} from "../src/libraries/UtilsLib.sol"; @@ -912,6 +912,24 @@ contract LiquidationTest is BaseTest { assertEq(midnight.collateral(id, borrower, 0), 0, "collateral withdrawn"); } + function testFullBadDebtTakeReverts(uint256 units) public { + units = bound(units, 10, MAX_UNITS); + collateralize(market, borrower, units); + setupMarket(market, units); + + Oracle(market.collateralParams[0].oracle).setPrice(0); + midnight.liquidate(market, 0, 0, 0, borrower, false, address(this), address(0), ""); + assertEq(midnight.lossFactor(id), type(uint128).max, "loss factor"); + + // The market is now permanently unusable: any take reverts. + Offer memory borrowerOffer = _setupMarketOffer(market); + deal(address(loanToken), lender, units); + + vm.expectRevert(IMidnight.MarketLossFactorMaxedOut.selector); + vm.prank(lender); + midnight.take(borrowerOffer, hex"", units, lender, address(0), address(0), hex""); + } + // helpers. /// @dev Bad debt as computed in liquidate diff --git a/test/OtherFunctionsTest.sol b/test/OtherFunctionsTest.sol index d0804fa5e..ea131bc14 100644 --- a/test/OtherFunctionsTest.sol +++ b/test/OtherFunctionsTest.sol @@ -168,6 +168,23 @@ contract OtherFunctionsTest is BaseTest { assertEq(callback.recordedData(), data, "data"); } + function testRepayCallbackWrongReturnValue(uint256 units, uint256 repaid, bytes memory data) public { + units = bound(units, 1, MAX_UNITS); + repaid = bound(repaid, 1, units); + collateralize(market, borrower, units); + setupMarket(market, units); + skip(99); + + address callback = address(new InvalidRepayCallback()); + deal(address(loanToken), callback, repaid); + vm.prank(callback); + loanToken.approve(address(midnight), repaid); + + vm.expectRevert(IMidnight.WrongRepayCallbackReturnValue.selector); + vm.prank(borrower); + midnight.repay(market, repaid, borrower, callback, data); + } + function testWithdraw(uint256 units, uint256 withdraw) public { units = bound(units, 1, MAX_UNITS); withdraw = bound(withdraw, 1, units); @@ -832,3 +849,9 @@ contract RepayCallback { return _recordedMarket; } } + +contract InvalidRepayCallback is IRepayCallback { + function onRepay(bytes32, Market memory, uint256, address, bytes memory) external pure returns (bytes32) { + return bytes32(0); + } +} diff --git a/test/SettersTest.sol b/test/SettersTest.sol index aa3af9734..f382cc920 100644 --- a/test/SettersTest.sol +++ b/test/SettersTest.sol @@ -327,6 +327,41 @@ contract SettersTest is BaseTest { midnight.touchMarket(market); } + function testTouchMarketRejectsMaxLifTooHigh() public { + uint256 liquidationCursor = 0.999e18; + midnight.enableLiquidationCursor(liquidationCursor); + + uint256 lltv = 0.5e18; + midnight.enableLltv(lltv); + + // maxLif = 1998001998001998001, which is <= 2 WAD (so InvalidMaxLif passes) but + // lltv * maxLif = 999000999000999000.5e18 > 0.999e18 * WAD, so MaxLifTooHigh trips. + uint256 _maxLif = maxLif(lltv, liquidationCursor); + assertLe(_maxLif, 2 * WAD, "maxLif below two WAD"); + assertGt(lltv * _maxLif, 0.999 ether * WAD, "lltv * maxLif above bound"); + + CollateralParams[] memory collateralParams = new CollateralParams[](1); + collateralParams[0] = CollateralParams({ + token: address(collateralToken1), + lltv: lltv, + liquidationCursor: liquidationCursor, + oracle: address(oracle1) + }); + Market memory market = Market({ + chainId: block.chainid, + midnight: address(midnight), + loanToken: address(loanToken), + maturity: vm.getBlockTimestamp() + 1 days, + collateralParams: collateralParams, + rcfThreshold: 0, + enterGate: address(0), + liquidatorGate: address(0) + }); + + vm.expectRevert(IMidnight.MaxLifTooHigh.selector); + midnight.touchMarket(market); + } + // Default settlement fee tests function testSettlementFeeRevertsWhenNotCreated() public { From 4b9d2e7faaa13fa8a3c4fcbffe9dbe8296cc32a7 Mon Sep 17 00:00:00 2001 From: peyha Date: Tue, 11 Aug 2026 16:04:27 +0200 Subject: [PATCH 071/159] test: periphery coverage --- test/EcrecoverAuthorizerTest.sol | 12 ++++++++++++ test/TakeAmountsTest.sol | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/test/EcrecoverAuthorizerTest.sol b/test/EcrecoverAuthorizerTest.sol index 9ad91bd78..495d1a90b 100644 --- a/test/EcrecoverAuthorizerTest.sol +++ b/test/EcrecoverAuthorizerTest.sol @@ -116,6 +116,18 @@ contract EcrecoverAuthorizerTest is BaseTest { assertEq(ecrecoverAuthorizer.nonce(borrower), 0); } + function testEcrecoverAuthorizerEcrecoverReturnsZero() public { + Authorization memory auth = makeAuthorization(borrower, lender, true); + Signature memory sig = signAuthorization(auth, borrower); + sig.v = 0; // Invalid v (valid values are 27/28) -> ecrecover returns address(0). + + vm.expectRevert(IEcrecoverAuthorizer.InvalidSignature.selector); + ecrecoverAuthorizer.setIsAuthorized(auth, sig); + + assertEq(midnight.isAuthorized(borrower, lender), false); + assertEq(ecrecoverAuthorizer.nonce(borrower), 0); + } + function testEcrecoverAuthorizerExpired() public { Authorization memory auth = makeAuthorization(borrower, lender, true); auth.deadline = vm.getBlockTimestamp() - 1; diff --git a/test/TakeAmountsTest.sol b/test/TakeAmountsTest.sol index e12d0ca4c..735e86c15 100644 --- a/test/TakeAmountsTest.sol +++ b/test/TakeAmountsTest.sol @@ -114,6 +114,26 @@ contract TakeAmountsTest is BaseTest { assertEq(buyerAssets, targetBuyerAssets, "e2e buyerAssets"); } + function buyerAssetsToUnitsExternal(bytes32 _id, Offer memory _offer, uint256 targetBuyerAssets) + external + view + returns (uint256) + { + return TakeAmountsLib.buyerAssetsToUnits(address(midnight), _id, _offer, targetBuyerAssets); + } + + function testBuyerAssetsToUnitsRevertsWhenBuyerPriceAboveWad(uint256 settlementFee0, uint256 settlementFee1) + public + { + uint256 settlementFee = _setSettlementFees(settlementFee0, settlementFee1); + vm.assume(settlementFee > 0); + offer.tick = MAX_TICK; + assertEq(TickLib.tickToPrice(offer.tick), WAD, "offer price at MAX_TICK"); + + vm.expectRevert(TickLib.PriceGreaterThanOne.selector); + this.buyerAssetsToUnitsExternal(id, offer, 1); + } + function testSellerAssetsToUnitsBuyerIsLender( uint256 targetSellerAssets, uint256 tick, From bac71f7df9e5a6eb01f42437954c406db0ab1a20 Mon Sep 17 00:00:00 2001 From: peyha Date: Tue, 11 Aug 2026 16:30:55 +0200 Subject: [PATCH 072/159] chore: fmt --- test/SettersTest.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/SettersTest.sol b/test/SettersTest.sol index f382cc920..11a5834d1 100644 --- a/test/SettersTest.sol +++ b/test/SettersTest.sol @@ -342,10 +342,7 @@ contract SettersTest is BaseTest { CollateralParams[] memory collateralParams = new CollateralParams[](1); collateralParams[0] = CollateralParams({ - token: address(collateralToken1), - lltv: lltv, - liquidationCursor: liquidationCursor, - oracle: address(oracle1) + token: address(collateralToken1), lltv: lltv, liquidationCursor: liquidationCursor, oracle: address(oracle1) }); Market memory market = Market({ chainId: block.chainid, From c02787f9d2065d51e514fd8bccc53d2e70f75aec Mon Sep 17 00:00:00 2001 From: peyha Date: Wed, 12 Aug 2026 18:28:13 +0200 Subject: [PATCH 073/159] feat: min rollable debt --- src/periphery/README.md | 8 +- .../BlueFallbackRolling.sol | 27 +- .../interfaces/IBlueFallbackRolling.sol | 4 + test/BlueFallbackRollingTest.sol | 447 ++++++++++++++++-- 4 files changed, 437 insertions(+), 49 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index c970c2081..45e631ad6 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -29,9 +29,11 @@ it to repay Midnight, and rewards the caller from the additional Blue borrow. Ro or a proportional partial amount. Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight -and Blue. Each configuration selects a Blue market, start timestamp, and caller incentive, and can later be disabled. -The caller incentive is a percentage of the debt and is capped at 100%. A roll requires the borrower to have exactly -one activated Midnight collateral, matching the collateral token of the configured Blue market. +and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and +can later be disabled. The caller incentive is a percentage of the debt and is capped at 100%. The minimum rollable +amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight +debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight +collateral, matching the collateral token of the configured Blue market. ### `EcrecoverAuthorizer` diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index b109895ae..a8ebd7b11 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,6 +28,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. + /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the + /// whole remaining Midnight debt. function setConfig( bytes32 midnightId, bytes32 blueId, @@ -35,16 +37,20 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, + uint128 minRollableAssets, bool enabled ) external override { require(start < end, EndNotAfterStart()); require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); - isConfig[msg.sender][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))] = - enabled; + bytes32 configId = + keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets)); + isConfig[msg.sender][configId] = enabled; - emit SetConfig(msg.sender, midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, enabled); + emit SetConfig( + msg.sender, midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets, enabled + ); } function roll( @@ -55,14 +61,14 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, + uint128 minRollableAssets, uint256 assets ) external override { bytes32 midnightId = IdLib.toId(midnightMarket); bytes32 blueId = Id.unwrap(blueMarketParams.id()); - require( - isConfig[user][keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd))], - NotConfigured() - ); + bytes32 configId = + keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets)); + require(isConfig[user][configId], NotConfigured()); require(blueMarketParams.loanToken == midnightMarket.loanToken, InconsistentLoanToken()); require(block.timestamp >= start, NotStarted()); require(block.timestamp <= end, Ended()); @@ -75,9 +81,12 @@ contract BlueFallbackRolling is IBlueFallbackRolling { ); require(midnightMarket.collateralParams[collateralIndex].lltv <= blueMarketParams.lltv, BlueLltvTooLow()); + uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); + require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); + // Round in favor of the Midnight position. - uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex) - .mulDivDown(assets, IMidnight(MIDNIGHT).debt(midnightId, user)); + uint256 collateralAssets = + IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex).mulDivDown(assets, debtAssets); // Round against the roller. uint256 incentiveFactor = incentiveAtEnd >= incentiveAtStart ? incentiveAtStart diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index d15e5aac6..6830225c3 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -18,6 +18,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { error NotBlue(); error NotConfigured(); error NotStarted(); + error RollableAssetsTooLow(); /// EVENTS /// event SetConfig( @@ -28,6 +29,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { uint256 end, uint256 incentiveAtStart, uint256 incentiveAtEnd, + uint256 minRollableAssets, bool enabled ); event Roll( @@ -53,6 +55,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, + uint128 minRollableAssets, bool enabled ) external; function roll( @@ -63,6 +66,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, + uint128 minRollableAssets, uint256 assets ) external; } diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 7e6610cac..fe438a894 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -19,6 +19,7 @@ contract BlueFallbackRollingTest is BaseTest { uint64 internal constant INCENTIVE_AT_END = 0.001e18; uint64 internal constant MAX_INCENTIVE = 1e18; uint256 internal constant DEBT = 10_000e18; + uint128 internal constant MIN_ROLLABLE_ASSETS = 2_500e18; address internal keeper = makeAddr("keeper"); IMorpho internal blue; @@ -94,6 +95,7 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); } @@ -104,7 +106,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); uint256 incentiveAssets = DEBT * INCENTIVE_AT_END / WAD; @@ -124,7 +134,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, debtAssets + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + debtAssets ); uint256 incentiveAssets = debtAssets * INCENTIVE_AT_END / WAD; @@ -149,13 +167,22 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_START, + MIN_ROLLABLE_ASSETS, true ); vm.warp(start + elapsed); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_START, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_START, + MIN_ROLLABLE_ASSETS, + DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_START / WAD); @@ -167,7 +194,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_END / WAD); @@ -180,7 +215,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * expectedIncentive(elapsed) / WAD); @@ -198,13 +241,22 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_END, INCENTIVE_AT_START, + MIN_ROLLABLE_ASSETS, true ); vm.warp(start + elapsed); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_END, INCENTIVE_AT_START, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_END, + INCENTIVE_AT_START, + MIN_ROLLABLE_ASSETS, + DEBT ); uint256 duration = end - start; @@ -226,13 +278,22 @@ contract BlueFallbackRollingTest is BaseTest { lateEnd, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); vm.warp(midnightMarket.maturity); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, lateEnd, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + lateEnd, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); uint256 elapsed = midnightMarket.maturity - start; @@ -245,7 +306,15 @@ contract BlueFallbackRollingTest is BaseTest { function testRollAtStartPaysTheStartIncentive() public { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); assertEq(loanToken.balanceOf(keeper), DEBT * INCENTIVE_AT_START / WAD); @@ -262,13 +331,22 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); vm.expectRevert(IBlueFallbackRolling.NotStarted.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, futureStart, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + futureStart, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -279,7 +357,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.Ended.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -289,7 +375,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -297,7 +391,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end + 1, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end + 1, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -311,13 +413,22 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); vm.expectRevert(IBlueFallbackRolling.InconsistentLoanToken.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -327,7 +438,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncorrectActivatedCollateral.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -341,7 +460,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.InconsistentCollateralToken.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -360,13 +487,22 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); vm.expectRevert(IBlueFallbackRolling.BlueLltvTooLow.selector); vm.prank(keeper); fallbackContract.roll( - midnightMarket, lowBlueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + lowBlueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -382,7 +518,11 @@ contract BlueFallbackRollingTest is BaseTest { } function testSetConfig() public view { - assertTrue(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); + assertTrue( + fallbackContract.isConfig( + borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS) + ) + ); } function testSetConfigRevertsForTooLargeIncentiveAtEnd() public { @@ -390,7 +530,14 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, INCENTIVE_AT_START, incentiveAtEnd, true + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + incentiveAtEnd, + MIN_ROLLABLE_ASSETS, + true ); } @@ -399,7 +546,14 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, incentiveAtStart, MAX_INCENTIVE, true + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + incentiveAtStart, + MAX_INCENTIVE, + MIN_ROLLABLE_ASSETS, + true ); } @@ -412,6 +566,7 @@ contract BlueFallbackRollingTest is BaseTest { start - 1, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); } @@ -425,6 +580,7 @@ contract BlueFallbackRollingTest is BaseTest { start, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, true ); } @@ -432,10 +588,19 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, MAX_INCENTIVE, MAX_INCENTIVE, true + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + MAX_INCENTIVE, + MAX_INCENTIVE, + MIN_ROLLABLE_ASSETS, + true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, end, MAX_INCENTIVE, MAX_INCENTIVE))); + assertTrue( + fallbackContract.isConfig(borrower, configId(start, end, MAX_INCENTIVE, MAX_INCENTIVE, MIN_ROLLABLE_ASSETS)) + ); } function testSetConfigCanDisable() public { @@ -447,14 +612,27 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, false ); - assertFalse(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); + assertFalse( + fallbackContract.isConfig( + borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS) + ) + ); vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } @@ -462,11 +640,26 @@ contract BlueFallbackRollingTest is BaseTest { uint64 otherStart = start + 1; vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE, true + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + otherStart, + end, + MAX_INCENTIVE, + MAX_INCENTIVE, + MIN_ROLLABLE_ASSETS, + true ); - assertTrue(fallbackContract.isConfig(borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END))); - assertTrue(fallbackContract.isConfig(borrower, configId(otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE))); + assertTrue( + fallbackContract.isConfig( + borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS) + ) + ); + assertTrue( + fallbackContract.isConfig( + borrower, configId(otherStart, end, MAX_INCENTIVE, MAX_INCENTIVE, MIN_ROLLABLE_ASSETS) + ) + ); } function testSetConfigEmitsSetConfig() public { @@ -479,6 +672,7 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, false ); @@ -490,6 +684,7 @@ contract BlueFallbackRollingTest is BaseTest { end, INCENTIVE_AT_START, INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, false ); } @@ -511,18 +706,28 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT ); } function testRollTransfersNoIncentiveWhenTheIncentiveIsZero(uint256 elapsed) public { elapsed = bound(elapsed, 0, end - start); vm.prank(borrower); - fallbackContract.setConfig(toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, 0, 0, true); + fallbackContract.setConfig( + toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, 0, 0, MIN_ROLLABLE_ASSETS, true + ); vm.warp(start + elapsed); vm.prank(keeper); - fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, end, 0, 0, DEBT); + fallbackContract.roll(midnightMarket, blueMarketParams, borrower, start, end, 0, 0, MIN_ROLLABLE_ASSETS, DEBT); assertEq(loanToken.balanceOf(keeper), 0); assertEq(loanToken.balanceOf(address(fallbackContract)), 0); @@ -531,10 +736,162 @@ contract BlueFallbackRollingTest is BaseTest { /// @dev Rolling with zero assets reverts in Blue's supply collateral. function testRollRevertsForZeroAssets() public { + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + 0, + true + ); + vm.expectRevert(bytes("zero assets")); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, 0 + midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, 0, 0 + ); + } + + function testRollRevertsForAssetsBelowMinRollableAssets() public { + vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + MIN_ROLLABLE_ASSETS - 1 + ); + } + + function testRollAtMinRollableAssets() public { + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + MIN_ROLLABLE_ASSETS + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - MIN_ROLLABLE_ASSETS); + } + + function testRollAllowsFullRollBelowMinRollableAssets() public { + uint128 minRollableAssets = type(uint128).max; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + DEBT + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + } + + function testRollAllowsFullRollOfRemainderBelowMinRollableAssets() public { + uint256 remainder = MIN_ROLLABLE_ASSETS - 1; + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT - remainder + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), remainder); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + remainder + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); + } + + function testRollRevertsForUnconfiguredMinRollableAssets() public { + vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS + 1, + DEBT + ); + } + + function testSetConfigDoesNotReplaceConfigWithOtherMinRollableAssets() public { + uint128 otherMinRollableAssets = MIN_ROLLABLE_ASSETS + 1; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + otherMinRollableAssets, + true + ); + + assertTrue( + fallbackContract.isConfig( + borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS) + ) + ); + assertTrue( + fallbackContract.isConfig( + borrower, configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, otherMinRollableAssets) + ) ); } @@ -542,7 +899,15 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(stdError.arithmeticError); vm.prank(keeper); fallbackContract.roll( - midnightMarket, blueMarketParams, borrower, start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, DEBT + 1 + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT + 1 ); } @@ -551,14 +916,22 @@ contract BlueFallbackRollingTest is BaseTest { return INCENTIVE_AT_START + (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed / duration; } - function configId(uint64 _start, uint64 _end, uint64 incentiveAtStart, uint64 incentiveAtEnd) - internal - view - returns (bytes32) - { + function configId( + uint64 _start, + uint64 _end, + uint64 incentiveAtStart, + uint64 incentiveAtEnd, + uint128 minRollableAssets + ) internal view returns (bytes32) { return keccak256( abi.encode( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), _start, _end, incentiveAtStart, incentiveAtEnd + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + _start, + _end, + incentiveAtStart, + incentiveAtEnd, + minRollableAssets ) ); } From df175fefe3cf12a122edec7dff0e9ac4bd849358 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 14 Aug 2026 12:13:36 +0200 Subject: [PATCH 074/159] fix: partial roll when below minrollableassets --- src/periphery/README.md | 4 +- .../BlueFallbackRolling.sol | 7 +- test/BlueFallbackRollingTest.sol | 261 ++++++++++++++++++ 3 files changed, 267 insertions(+), 5 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index 45e631ad6..2fed42f10 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -31,8 +31,8 @@ or a proportional partial amount. Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and can later be disabled. The caller incentive is a percentage of the debt and is capped at 100%. The minimum rollable -amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight -debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight +amount is the smallest debt a single roll can migrate. It no longer applies once the remaining Midnight debt is at most +that amount. A roll requires the borrower to have exactly one activated Midnight collateral, matching the collateral token of the configured Blue market. ### `EcrecoverAuthorizer` diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index a8ebd7b11..356fd330d 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,8 +28,9 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. - /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the - /// whole remaining Midnight debt. + /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue. It does not apply once the + /// remaining Midnight debt is at most `minRollableAssets`, in which case any amount can be rolled. Setting + /// `minRollableAssets` above the Midnight debt thus disables the constraint entirely. function setConfig( bytes32 midnightId, bytes32 blueId, @@ -82,7 +83,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { require(midnightMarket.collateralParams[collateralIndex].lltv <= blueMarketParams.lltv, BlueLltvTooLow()); uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); - require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); + require(assets >= minRollableAssets || debtAssets <= minRollableAssets, RollableAssetsTooLow()); // Round in favor of the Midnight position. uint256 collateralAssets = diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index fe438a894..7639fec1d 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -20,6 +20,7 @@ contract BlueFallbackRollingTest is BaseTest { uint64 internal constant MAX_INCENTIVE = 1e18; uint256 internal constant DEBT = 10_000e18; uint128 internal constant MIN_ROLLABLE_ASSETS = 2_500e18; + uint256 internal constant MIN_FUZZED_ASSETS = 0.0001e18; address internal keeper = makeAddr("keeper"); IMorpho internal blue; @@ -788,6 +789,100 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - MIN_ROLLABLE_ASSETS); } + /// @dev A `minRollableAssets` above the Midnight debt leaves rolls unconstrained, including partial ones. + function testRollAllowsPartialRollWhenDebtIsBelowMinRollableAssets() public { + uint128 minRollableAssets = uint128(DEBT + 1); + uint256 assets = DEBT / 4; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + assets + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - assets); + } + + /// @dev The constraint stops applying as soon as the debt reaches `minRollableAssets`, bound included. + function testRollAllowsPartialRollWhenDebtEqualsMinRollableAssets() public { + uint128 minRollableAssets = uint128(DEBT); + uint256 assets = DEBT / 4; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + assets + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - assets); + } + + /// @dev One wei of debt above `minRollableAssets` is enough for the constraint to apply. + function testRollRevertsWhenDebtIsJustAboveMinRollableAssets() public { + uint128 minRollableAssets = uint128(DEBT - 1); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + + vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + minRollableAssets - 1 + ); + } + function testRollAllowsFullRollBelowMinRollableAssets() public { uint128 minRollableAssets = type(uint128).max; vm.prank(borrower); @@ -853,6 +948,39 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); } + /// @dev A remainder below `minRollableAssets` does not have to be rolled in one go, nor matched exactly. + function testRollAllowsPartialRollOfRemainderBelowMinRollableAssets() public { + uint256 remainder = MIN_ROLLABLE_ASSETS - 1; + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + DEBT - remainder + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + remainder / 2 + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), remainder - remainder / 2); + } + function testRollRevertsForUnconfiguredMinRollableAssets() public { vm.expectRevert(IBlueFallbackRolling.NotConfigured.selector); vm.prank(keeper); @@ -895,6 +1023,139 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testRollRevertsWithFuzzedMinRollableAssets(uint128 minRollableAssets, uint256 assets) public { + minRollableAssets = uint128(bound(minRollableAssets, 1, DEBT - 1)); + assets = bound(assets, 0, minRollableAssets - 1); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + + vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + assets + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT); + assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), totalCollateralAssets); + assertEq(loanToken.balanceOf(keeper), 0); + } + + function testRollSucceedsWithFuzzedMinRollableAssets(uint128 minRollableAssets, uint256 assets) public { + minRollableAssets = uint128(bound(minRollableAssets, 0, 2 * DEBT)); + uint256 minAssets = MIN_FUZZED_ASSETS; + if (DEBT > minRollableAssets && minRollableAssets > MIN_FUZZED_ASSETS) minAssets = minRollableAssets; + assets = bound(assets, minAssets, DEBT); + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + assets + ); + + uint256 collateralAssets = totalCollateralAssets * assets / DEBT; + assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - assets); + assertEq( + midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), + totalCollateralAssets - collateralAssets + ); + assertEq(blue.position(blueMarketParams.id(), borrower).collateral, collateralAssets); + assertEq(loanToken.balanceOf(keeper), assets * INCENTIVE_AT_START / WAD); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + } + + function testRollAllowsFullRollOfRemainderWithFuzzedMinRollableAssets( + uint128 minRollableAssets, + uint256 firstAssets + ) public { + minRollableAssets = uint128(bound(minRollableAssets, 1, DEBT - MIN_FUZZED_ASSETS)); + firstAssets = bound( + firstAssets, + minRollableAssets > MIN_FUZZED_ASSETS ? minRollableAssets : MIN_FUZZED_ASSETS, + DEBT - MIN_FUZZED_ASSETS + ); + uint256 remainder = DEBT - firstAssets; + vm.prank(borrower); + fallbackContract.setConfig( + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + true + ); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + firstAssets + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), remainder); + + vm.prank(keeper); + fallbackContract.roll( + midnightMarket, + blueMarketParams, + borrower, + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + minRollableAssets, + remainder + ); + + assertEq(midnight.debt(toId(midnightMarket), borrower), 0); + assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); + assertEq(loanToken.balanceOf(address(fallbackContract)), 0); + } + function testRollRevertsForAssetsGreaterThanDebt() public { vm.expectRevert(stdError.arithmeticError); vm.prank(keeper); From 9c1031a487bd8a02b66b0548dfd9dfc03276f194 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 14 Aug 2026 14:39:49 +0200 Subject: [PATCH 075/159] feat: revert to assets=debt condition --- src/periphery/README.md | 4 +- .../BlueFallbackRolling.sol | 7 ++- test/BlueFallbackRollingTest.sol | 51 +++---------------- 3 files changed, 13 insertions(+), 49 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index 2fed42f10..45e631ad6 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -31,8 +31,8 @@ or a proportional partial amount. Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and can later be disabled. The caller incentive is a percentage of the debt and is capped at 100%. The minimum rollable -amount is the smallest debt a single roll can migrate. It no longer applies once the remaining Midnight debt is at most -that amount. A roll requires the borrower to have exactly one activated Midnight +amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight +debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight collateral, matching the collateral token of the configured Blue market. ### `EcrecoverAuthorizer` diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 356fd330d..a8ebd7b11 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -28,9 +28,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { } /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. - /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue. It does not apply once the - /// remaining Midnight debt is at most `minRollableAssets`, in which case any amount can be rolled. Setting - /// `minRollableAssets` above the Midnight debt thus disables the constraint entirely. + /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the + /// whole remaining Midnight debt. function setConfig( bytes32 midnightId, bytes32 blueId, @@ -83,7 +82,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { require(midnightMarket.collateralParams[collateralIndex].lltv <= blueMarketParams.lltv, BlueLltvTooLow()); uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); - require(assets >= minRollableAssets || debtAssets <= minRollableAssets, RollableAssetsTooLow()); + require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); // Round in favor of the Midnight position. uint256 collateralAssets = diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 7639fec1d..7dd6c2fb7 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -789,8 +789,7 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - MIN_ROLLABLE_ASSETS); } - /// @dev A `minRollableAssets` above the Midnight debt leaves rolls unconstrained, including partial ones. - function testRollAllowsPartialRollWhenDebtIsBelowMinRollableAssets() public { + function testRollRevertsForPartialRollWhenDebtIsBelowMinRollableAssets() public { uint128 minRollableAssets = uint128(DEBT + 1); uint256 assets = DEBT / 4; vm.prank(borrower); @@ -805,6 +804,7 @@ contract BlueFallbackRollingTest is BaseTest { true ); + vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -817,40 +817,6 @@ contract BlueFallbackRollingTest is BaseTest { minRollableAssets, assets ); - - assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - assets); - } - - /// @dev The constraint stops applying as soon as the debt reaches `minRollableAssets`, bound included. - function testRollAllowsPartialRollWhenDebtEqualsMinRollableAssets() public { - uint128 minRollableAssets = uint128(DEBT); - uint256 assets = DEBT / 4; - vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), - Id.unwrap(blueMarketParams.id()), - start, - end, - INCENTIVE_AT_START, - INCENTIVE_AT_END, - minRollableAssets, - true - ); - - vm.prank(keeper); - fallbackContract.roll( - midnightMarket, - blueMarketParams, - borrower, - start, - end, - INCENTIVE_AT_START, - INCENTIVE_AT_END, - minRollableAssets, - assets - ); - - assertEq(midnight.debt(toId(midnightMarket), borrower), DEBT - assets); } /// @dev One wei of debt above `minRollableAssets` is enough for the constraint to apply. @@ -948,8 +914,7 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex), 0); } - /// @dev A remainder below `minRollableAssets` does not have to be rolled in one go, nor matched exactly. - function testRollAllowsPartialRollOfRemainderBelowMinRollableAssets() public { + function testRollRevertsForPartialRollOfRemainderBelowMinRollableAssets() public { uint256 remainder = MIN_ROLLABLE_ASSETS - 1; vm.prank(keeper); @@ -965,6 +930,7 @@ contract BlueFallbackRollingTest is BaseTest { DEBT - remainder ); + vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -977,8 +943,6 @@ contract BlueFallbackRollingTest is BaseTest { MIN_ROLLABLE_ASSETS, remainder / 2 ); - - assertEq(midnight.debt(toId(midnightMarket), borrower), remainder - remainder / 2); } function testRollRevertsForUnconfiguredMinRollableAssets() public { @@ -1024,8 +988,8 @@ contract BlueFallbackRollingTest is BaseTest { } function testRollRevertsWithFuzzedMinRollableAssets(uint128 minRollableAssets, uint256 assets) public { - minRollableAssets = uint128(bound(minRollableAssets, 1, DEBT - 1)); - assets = bound(assets, 0, minRollableAssets - 1); + minRollableAssets = uint128(bound(minRollableAssets, 1, 2 * DEBT)); + assets = bound(assets, 0, minRollableAssets < DEBT ? minRollableAssets - 1 : DEBT - 1); vm.prank(borrower); fallbackContract.setConfig( toId(midnightMarket), @@ -1061,7 +1025,8 @@ contract BlueFallbackRollingTest is BaseTest { function testRollSucceedsWithFuzzedMinRollableAssets(uint128 minRollableAssets, uint256 assets) public { minRollableAssets = uint128(bound(minRollableAssets, 0, 2 * DEBT)); uint256 minAssets = MIN_FUZZED_ASSETS; - if (DEBT > minRollableAssets && minRollableAssets > MIN_FUZZED_ASSETS) minAssets = minRollableAssets; + if (minRollableAssets > MIN_FUZZED_ASSETS) minAssets = minRollableAssets; + if (minAssets > DEBT) minAssets = DEBT; assets = bound(assets, minAssets, DEBT); vm.prank(borrower); fallbackContract.setConfig( From 642713aad3d2fb9d4d8ee2b00fb95a9ca4b7d5b5 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 14 Aug 2026 14:46:09 +0200 Subject: [PATCH 076/159] doc: readme --- src/periphery/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index 45e631ad6..d35e0f78b 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -24,9 +24,8 @@ The factory records callbacks in `callbackOf` and `isBlueBuyCallback`. ### `BlueFallbackRolling` Permissionlessly refinances a borrower's Midnight debt into a user-selected Morpho Blue market once the Midnight market -reaches the configured start timestamp. It supplies the selected collateral to Blue through a callback, borrows against -it to repay Midnight, and rewards the caller from the additional Blue borrow. Rolls may migrate all debt and collateral -or a proportional partial amount. +reaches the configured start timestamp. It supplies the activated collateral to Blue through a callback, borrows against +it to repay Midnight, and rewards the caller. Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and From 7670ea8cc4c8b9d6c6057af63616541238d49c9a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 12 Aug 2026 16:11:17 +0000 Subject: [PATCH 077/159] Remove lltv check --- .../BlueFallbackRolling.sol | 4 +-- .../interfaces/IBlueFallbackRolling.sol | 1 - test/BlueFallbackRollingTest.sol | 34 ------------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index a8ebd7b11..e87150b49 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -27,7 +27,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } - /// @dev The LLTV of the Blue market must be greater than or equal to the LLTV of the Midnight market. + /// @dev Users must make sure that the oracle and the LLTV of the Blue market are appropriate, otherwise their + /// position can be liquidated on Blue. /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the /// whole remaining Midnight debt. function setConfig( @@ -79,7 +80,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { blueMarketParams.collateralToken == midnightMarket.collateralParams[collateralIndex].token, InconsistentCollateralToken() ); - require(midnightMarket.collateralParams[collateralIndex].lltv <= blueMarketParams.lltv, BlueLltvTooLow()); uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 6830225c3..38c5b84f8 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -8,7 +8,6 @@ import {Market} from "../../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// - error BlueLltvTooLow(); error Ended(); error EndNotAfterStart(); error IncentiveTooHigh(); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 7dd6c2fb7..16b452a96 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -473,40 +473,6 @@ contract BlueFallbackRollingTest is BaseTest { ); } - function testRollRevertsWhenBlueLltvIsLowerThanMidnightLltv() public { - uint256 lowLltv = LLTV - 1; - blue.enableLltv(lowLltv); - MarketParams memory lowBlueMarketParams = blueMarketParams; - lowBlueMarketParams.lltv = lowLltv; - blue.createMarket(lowBlueMarketParams); - - vm.prank(borrower); - fallbackContract.setConfig( - toId(midnightMarket), - Id.unwrap(lowBlueMarketParams.id()), - start, - end, - INCENTIVE_AT_START, - INCENTIVE_AT_END, - MIN_ROLLABLE_ASSETS, - true - ); - - vm.expectRevert(IBlueFallbackRolling.BlueLltvTooLow.selector); - vm.prank(keeper); - fallbackContract.roll( - midnightMarket, - lowBlueMarketParams, - borrower, - start, - end, - INCENTIVE_AT_START, - INCENTIVE_AT_END, - MIN_ROLLABLE_ASSETS, - DEBT - ); - } - function testSupplyCollateralCallbackRevertsIfCallerIsNotBlue() public { uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); vm.expectRevert(IBlueFallbackRolling.NotBlue.selector); From 88344c5e5c4808b0c18b7fe8787bd50eb072302e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 17:15:37 +0000 Subject: [PATCH 078/159] Reword lltv warning comment --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index e87150b49..361631aa9 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -27,8 +27,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } - /// @dev Users must make sure that the oracle and the LLTV of the Blue market are appropriate, otherwise their - /// position can be liquidated on Blue. + /// @dev Users must make sure that the oracle and the LLTV of the Blue market are appropriate; otherwise, they + /// risk getting the position on Blue liquidated. /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the /// whole remaining Midnight debt. function setConfig( From 82ff1771e30d1f630ae31f1c2bc4f707511bf038 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 17:19:02 +0000 Subject: [PATCH 079/159] Move lltv warning to contract natspec --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 361631aa9..5569232bb 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -13,6 +13,8 @@ import {IBlueFallbackRolling} from "./interfaces/IBlueFallbackRolling.sol"; import {SafeApproveLib} from "../libraries/SafeApproveLib.sol"; /// @dev Users must authorize this contract on both Midnight and Blue before their debt can be rolled. +/// @dev Users must make sure that the oracle and the LLTV of the Blue market are appropriate; otherwise, their +/// position on Blue could be left close to liquidation. contract BlueFallbackRolling is IBlueFallbackRolling { using MarketParamsLib for MarketParams; using UtilsLib for uint128; @@ -27,8 +29,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } - /// @dev Users must make sure that the oracle and the LLTV of the Blue market are appropriate; otherwise, they - /// risk getting the position on Blue liquidated. /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the /// whole remaining Midnight debt. function setConfig( From 38fa6f8d148e70f7cd3e01a9c36a888074a96c44 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 14 Aug 2026 15:28:50 +0200 Subject: [PATCH 080/159] chore: lint --- test/BlueFallbackRollingTest.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 16b452a96..14bf716cf 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -756,6 +756,7 @@ contract BlueFallbackRollingTest is BaseTest { } function testRollRevertsForPartialRollWhenDebtIsBelowMinRollableAssets() public { + // forge-lint: disable-next-line(unsafe-typecast) as DEBT + 1 < type(uint128).max uint128 minRollableAssets = uint128(DEBT + 1); uint256 assets = DEBT / 4; vm.prank(borrower); @@ -787,6 +788,7 @@ contract BlueFallbackRollingTest is BaseTest { /// @dev One wei of debt above `minRollableAssets` is enough for the constraint to apply. function testRollRevertsWhenDebtIsJustAboveMinRollableAssets() public { + // forge-lint: disable-next-line(unsafe-typecast) as DEBT - 1 < type(uint128).max uint128 minRollableAssets = uint128(DEBT - 1); vm.prank(borrower); fallbackContract.setConfig( From 77188c9488fc2d96a77cf63662644221d9c337d5 Mon Sep 17 00:00:00 2001 From: peyha Date: Fri, 14 Aug 2026 15:55:24 +0200 Subject: [PATCH 081/159] doc: readme --- src/periphery/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index d35e0f78b..afce4f2dc 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -24,8 +24,8 @@ The factory records callbacks in `callbackOf` and `isBlueBuyCallback`. ### `BlueFallbackRolling` Permissionlessly refinances a borrower's Midnight debt into a user-selected Morpho Blue market once the Midnight market -reaches the configured start timestamp. It supplies the activated collateral to Blue through a callback, borrows against -it to repay Midnight, and rewards the caller. +reaches the configured start timestamp. It supplies the activated collateral to Blue before, through a callback, borrowing against +it on Blue to reward the caller, repay the debt and withdraw the collateral on Midnight. Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and From b8508cd9c50438feb70ae4c8f84656e8e067762a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Aug 2026 08:05:11 +0000 Subject: [PATCH 082/159] [rolling fallback] append LTV note to rounding comment Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01QibthXUs7vNUykfNrPym2E --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 5569232bb..75c53ca54 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -84,7 +84,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); - // Round in favor of the Midnight position. + // Round in favor of the Midnight position. Thus, splitting the rolls can lower the blue final LTV. This is + // mitigated by the min rollable debt. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex).mulDivDown(assets, debtAssets); // Round against the roller. From aa0d660531632932af67709fc88c580507e8ca8f Mon Sep 17 00:00:00 2001 From: "prd-carapulse[bot]" <264278285+prd-carapulse[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:00:53 +0000 Subject: [PATCH 083/159] test: cover authorized fallback config setters Add regression coverage for delegated config writes and unauthorized callers. Co-authored-by: PA <50184410+peyha@users.noreply.github.com> --- test/BlueFallbackRollingTest.sol | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 14bf716cf..ce053e71d 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -656,6 +656,61 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigByMidnightAuthorizedCaller() public { + vm.prank(borrower); + midnight.setIsAuthorized(lender, true, borrower); + uint64 otherEnd = end + 1; + + vm.expectEmit(address(fallbackContract)); + emit IBlueFallbackRolling.SetConfig( + lender, + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + otherEnd, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + true + ); + + vm.prank(lender); + fallbackContract.setConfig( + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + otherEnd, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + true + ); + + assertTrue( + fallbackContract.isConfig( + borrower, configId(start, otherEnd, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS) + ) + ); + } + + function testSetConfigRevertsForUnauthorizedCaller() public { + vm.expectRevert(IBlueFallbackRolling.Unauthorized.selector); + vm.prank(keeper); + fallbackContract.setConfig( + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + true + ); + } + function testRollEmitsRoll() public { uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); vm.warp(end); From d4e32d3a2d039bb450fabc9f1fd2811daa56f417 Mon Sep 17 00:00:00 2001 From: "prd-carapulse[bot]" <264278285+prd-carapulse[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:07:11 +0000 Subject: [PATCH 084/159] feat: allow authorized fallback config setters Permit the borrower or any Midnight-authorized account to write the borrower keyed fallback configuration. Preserve caller attribution in SetConfig and reject unrelated callers. Co-authored-by: PA <50184410+peyha@users.noreply.github.com> --- src/periphery/README.md | 5 +-- .../BlueFallbackRolling.sol | 17 ++++++++-- .../interfaces/IBlueFallbackRolling.sol | 3 ++ test/BlueFallbackRollingTest.sol | 33 ++++++++++++++++++- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index afce4f2dc..01fcaf7ca 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -27,8 +27,9 @@ Permissionlessly refinances a borrower's Midnight debt into a user-selected Morp reaches the configured start timestamp. It supplies the activated collateral to Blue before, through a callback, borrowing against it on Blue to reward the caller, repay the debt and withdraw the collateral on Midnight. -Users may enable multiple fallback configurations per Midnight market and must authorize the contract on both Midnight -and Blue. Each configuration selects a Blue market, start timestamp, caller incentive, and minimum rollable amount, and +Users and accounts they authorize on Midnight may enable multiple fallback configurations per Midnight market. Users +must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller +incentive, and minimum rollable amount, and can later be disabled. The caller incentive is a percentage of the debt and is capped at 100%. The minimum rollable amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 75c53ca54..389b1097e 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -29,9 +29,11 @@ contract BlueFallbackRolling is IBlueFallbackRolling { BLUE = _blue; } + /// @dev The caller must be `user` or an address authorized for `user` on Midnight. /// @dev `minRollableAssets` is the minimum debt that a single roll can move to Blue, unless the roll moves the /// whole remaining Midnight debt. function setConfig( + address user, bytes32 midnightId, bytes32 blueId, uint64 start, @@ -45,12 +47,23 @@ contract BlueFallbackRolling is IBlueFallbackRolling { require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); + require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); + bytes32 configId = keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets)); - isConfig[msg.sender][configId] = enabled; + isConfig[user][configId] = enabled; emit SetConfig( - msg.sender, midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets, enabled + msg.sender, + user, + midnightId, + blueId, + start, + end, + incentiveAtStart, + incentiveAtEnd, + minRollableAssets, + enabled ); } diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 38c5b84f8..5728a3403 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -18,9 +18,11 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { error NotConfigured(); error NotStarted(); error RollableAssetsTooLow(); + error Unauthorized(); /// EVENTS /// event SetConfig( + address caller, address indexed user, bytes32 indexed midnightId, bytes32 indexed blueId, @@ -48,6 +50,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// FUNCTIONS /// function setConfig( + address user, bytes32 midnightId, bytes32 blueId, uint64 start, diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index ce053e71d..e398da5d1 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -90,6 +90,7 @@ contract BlueFallbackRollingTest is BaseTest { blue.setAuthorization(address(fallbackContract), true); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -162,6 +163,7 @@ contract BlueFallbackRollingTest is BaseTest { elapsed = bound(elapsed, 0, end - start); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -236,6 +238,7 @@ contract BlueFallbackRollingTest is BaseTest { elapsed = bound(elapsed, 0, end - start); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -273,6 +276,7 @@ contract BlueFallbackRollingTest is BaseTest { uint64 lateEnd = uint64(midnightMarket.maturity) + 1 days; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -326,6 +330,7 @@ contract BlueFallbackRollingTest is BaseTest { uint64 futureStart = uint64(vm.getBlockTimestamp() + 1); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), futureStart, @@ -408,6 +413,7 @@ contract BlueFallbackRollingTest is BaseTest { blueMarketParams.loanToken = makeAddr("otherLoanToken"); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -497,6 +503,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig( + address(this), toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -513,6 +520,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.expectRevert(IBlueFallbackRolling.IncentiveTooHigh.selector); fallbackContract.setConfig( + address(this), toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -527,6 +535,7 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigRevertsForEndBeforeStart() public { vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( + address(this), toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -541,6 +550,7 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigRevertsForEndAtStart() public { vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( + address(this), toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -555,6 +565,7 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -573,6 +584,7 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigCanDisable() public { vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -607,6 +619,7 @@ contract BlueFallbackRollingTest is BaseTest { uint64 otherStart = start + 1; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), otherStart, @@ -632,6 +645,7 @@ contract BlueFallbackRollingTest is BaseTest { function testSetConfigEmitsSetConfig() public { vm.expectEmit(address(fallbackContract)); emit IBlueFallbackRolling.SetConfig( + borrower, borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), @@ -645,6 +659,7 @@ contract BlueFallbackRollingTest is BaseTest { vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -744,7 +759,15 @@ contract BlueFallbackRollingTest is BaseTest { elapsed = bound(elapsed, 0, end - start); vm.prank(borrower); fallbackContract.setConfig( - toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, end, 0, 0, MIN_ROLLABLE_ASSETS, true + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + 0, + 0, + MIN_ROLLABLE_ASSETS, + true ); vm.warp(start + elapsed); @@ -760,6 +783,7 @@ contract BlueFallbackRollingTest is BaseTest { function testRollRevertsForZeroAssets() public { vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -816,6 +840,7 @@ contract BlueFallbackRollingTest is BaseTest { uint256 assets = DEBT / 4; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -847,6 +872,7 @@ contract BlueFallbackRollingTest is BaseTest { uint128 minRollableAssets = uint128(DEBT - 1); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -876,6 +902,7 @@ contract BlueFallbackRollingTest is BaseTest { uint128 minRollableAssets = type(uint128).max; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -988,6 +1015,7 @@ contract BlueFallbackRollingTest is BaseTest { uint128 otherMinRollableAssets = MIN_ROLLABLE_ASSETS + 1; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -1015,6 +1043,7 @@ contract BlueFallbackRollingTest is BaseTest { assets = bound(assets, 0, minRollableAssets < DEBT ? minRollableAssets - 1 : DEBT - 1); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -1053,6 +1082,7 @@ contract BlueFallbackRollingTest is BaseTest { assets = bound(assets, minAssets, DEBT); vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, @@ -1101,6 +1131,7 @@ contract BlueFallbackRollingTest is BaseTest { uint256 remainder = DEBT - firstAssets; vm.prank(borrower); fallbackContract.setConfig( + borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), start, From 829790997191baac927fa17168b5d958de5d6d2c Mon Sep 17 00:00:00 2001 From: "prd-carapulse[bot]" <264278285+prd-carapulse[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:24:20 +0000 Subject: [PATCH 085/159] test: require fallback config authorization first Lock in Unauthorized precedence when config parameters are also invalid. Co-authored-by: PA <50184410+peyha@users.noreply.github.com> --- test/BlueFallbackRollingTest.sol | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index e398da5d1..ea66d287f 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -726,6 +726,22 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigChecksAuthorizationFirst() public { + vm.expectRevert(IBlueFallbackRolling.Unauthorized.selector); + vm.prank(keeper); + fallbackContract.setConfig( + borrower, + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + start, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + true + ); + } + function testRollEmitsRoll() public { uint256 collateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); vm.warp(end); From 6a129c4de172ea7be19f7d33b85636510c10e998 Mon Sep 17 00:00:00 2001 From: "prd-carapulse[bot]" <264278285+prd-carapulse[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:32:42 +0000 Subject: [PATCH 086/159] fix: check fallback config authorization first Return Unauthorized before validating config parameters for callers that cannot act for the borrower. Co-authored-by: PA <50184410+peyha@users.noreply.github.com> --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 389b1097e..2c80cdc11 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -43,12 +43,11 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint128 minRollableAssets, bool enabled ) external override { + require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); require(start < end, EndNotAfterStart()); require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); - require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); - bytes32 configId = keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets)); isConfig[user][configId] = enabled; From 35143e5a69bff1e69e42c4229e6e3bff734ca07f Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 17 Aug 2026 10:50:52 +0200 Subject: [PATCH 087/159] feat: equality case for end start comp --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- test/BlueFallbackRollingTest.sol | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 2c80cdc11..ffc591fd0 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -44,7 +44,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { bool enabled ) external override { require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); - require(start < end, EndNotAfterStart()); + require(start <= end, EndNotAfterStart()); require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index ea66d287f..ef4fa65d7 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -547,21 +547,6 @@ contract BlueFallbackRollingTest is BaseTest { ); } - function testSetConfigRevertsForEndAtStart() public { - vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); - fallbackContract.setConfig( - address(this), - toId(midnightMarket), - Id.unwrap(blueMarketParams.id()), - start, - start, - INCENTIVE_AT_START, - INCENTIVE_AT_END, - MIN_ROLLABLE_ASSETS, - true - ); - } - function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( From f65b91ef1ce9f0b98bc0c0e3760bf3972b7eb6a2 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 17 Aug 2026 11:09:13 +0200 Subject: [PATCH 088/159] Revert "feat: equality case for end start comp" This reverts commit 7860808460759050499bda1b0d566a6cdc07af22. --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- test/BlueFallbackRollingTest.sol | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index ffc591fd0..2c80cdc11 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -44,7 +44,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { bool enabled ) external override { require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); - require(start <= end, EndNotAfterStart()); + require(start < end, EndNotAfterStart()); require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index ef4fa65d7..ea66d287f 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -547,6 +547,21 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigRevertsForEndAtStart() public { + vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); + fallbackContract.setConfig( + address(this), + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + start, + INCENTIVE_AT_START, + INCENTIVE_AT_END, + MIN_ROLLABLE_ASSETS, + true + ); + } + function testSetConfigAllowsOneIncentive() public { vm.prank(borrower); fallbackContract.setConfig( From 7d727f8da4ac292a1cd9268db8382ed207833267 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 17 Aug 2026 11:22:13 +0200 Subject: [PATCH 089/159] doc: periphery readme --- src/periphery/README.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index 01fcaf7ca..982ace094 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -23,17 +23,15 @@ The factory records callbacks in `callbackOf` and `isBlueBuyCallback`. ### `BlueFallbackRolling` -Permissionlessly refinances a borrower's Midnight debt into a user-selected Morpho Blue market once the Midnight market -reaches the configured start timestamp. It supplies the activated collateral to Blue before, through a callback, borrowing against -it on Blue to reward the caller, repay the debt and withdraw the collateral on Midnight. - -Users and accounts they authorize on Midnight may enable multiple fallback configurations per Midnight market. Users -must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, start timestamp, caller -incentive, and minimum rollable amount, and -can later be disabled. The caller incentive is a percentage of the debt and is capped at 100%. The minimum rollable -amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight -debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight -collateral, matching the collateral token of the configured Blue market. +Permissionlessly refinances a borrower's Midnight debt into a user-selected Morpho Blue market once the Midnight market reaches the configured start timestamp. +It supplies the activated collateral to Blue before, through a callback, borrowing against it on Blue to reward the caller, repay the debt and withdraw the collateral on Midnight. + +Users and accounts they authorize on Midnight may enable multiple fallback configurations per Midnight market. +Users must authorize the contract on both Midnight and Blue. +Each configuration selects a Blue market, a Midnight market, start timestamp, end timestamp, caller incentive at start, caller incentive at end, and minimum rollable amount, and can later be disabled. +The caller incentive is a percentage of the debt, is capped at 100% and evolves linearly between start and end. +The minimum rollable amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight debt, so a position can always be closed out. +A roll requires the borrower to have exactly one activated Midnight collateral, matching the collateral token of the configured Blue market. ### `EcrecoverAuthorizer` From 631c286e149f55c14b37fa5b1ea68ff0e5d0a3d9 Mon Sep 17 00:00:00 2001 From: PA <50184410+peyha@users.noreply.github.com> Date: Mon, 17 Aug 2026 11:33:53 +0200 Subject: [PATCH 090/159] Update src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: PA <50184410+peyha@users.noreply.github.com> --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 2c80cdc11..a1de72b64 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -96,7 +96,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); - // Round in favor of the Midnight position. Thus, splitting the rolls can lower the blue final LTV. This is + // Round in favor of the Midnight position. Thus, splitting the rolls can raise the blue final LTV. This is // mitigated by the min rollable debt. uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex).mulDivDown(assets, debtAssets); From c614e854390c36c7ed80c9911a9b754d2f31eefe Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 17 Aug 2026 11:39:46 +0200 Subject: [PATCH 091/159] refactor: inline interface --- .../interfaces/IBlueFallbackRolling.sol | 49 +++---------------- 1 file changed, 6 insertions(+), 43 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 5728a3403..d7a7bd1b4 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -20,28 +20,10 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { error RollableAssetsTooLow(); error Unauthorized(); + // forgefmt: disable-start /// EVENTS /// - event SetConfig( - address caller, - address indexed user, - bytes32 indexed midnightId, - bytes32 indexed blueId, - uint256 start, - uint256 end, - uint256 incentiveAtStart, - uint256 incentiveAtEnd, - uint256 minRollableAssets, - bool enabled - ); - event Roll( - address indexed caller, - address indexed user, - bytes32 indexed midnightId, - bytes32 blueId, - uint256 debtAssets, - uint256 collateralAssets, - uint256 incentiveAssets - ); + event SetConfig(address caller, address indexed user, bytes32 indexed midnightId, bytes32 indexed blueId, uint256 start, uint256 end, uint256 incentiveAtStart, uint256 incentiveAtEnd, uint256 minRollableAssets, bool enabled); + event Roll(address indexed caller, address indexed user, bytes32 indexed midnightId, bytes32 blueId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets); /// STORAGE GETTERS /// function MIDNIGHT() external view returns (address); @@ -49,26 +31,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { function isConfig(address user, bytes32 configId) external view returns (bool); /// FUNCTIONS /// - function setConfig( - address user, - bytes32 midnightId, - bytes32 blueId, - uint64 start, - uint64 end, - uint64 incentiveAtStart, - uint64 incentiveAtEnd, - uint128 minRollableAssets, - bool enabled - ) external; - function roll( - Market memory midnightMarket, - MarketParams memory blueMarketParams, - address user, - uint64 start, - uint64 end, - uint64 incentiveAtStart, - uint64 incentiveAtEnd, - uint128 minRollableAssets, - uint256 assets - ) external; + function setConfig(address user, bytes32 midnightId, bytes32 blueId, uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, uint128 minRollableAssets, bool enabled) external; + function roll(Market memory midnightMarket, MarketParams memory blueMarketParams, address user, uint64 start, uint64 end, uint64 incentiveAtStart, uint64 incentiveAtEnd, uint128 minRollableAssets, uint256 assets) external; + // forgefmt: disable-end } From db3f6007e3c38dd732774fde354476f956c7c8c6 Mon Sep 17 00:00:00 2001 From: peyha Date: Mon, 17 Aug 2026 11:50:35 +0200 Subject: [PATCH 092/159] refactor: rolled assets too low --- .../blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- .../interfaces/IBlueFallbackRolling.sol | 2 +- test/BlueFallbackRollingTest.sol | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index a1de72b64..bc41be5cd 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -94,7 +94,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { ); uint256 debtAssets = IMidnight(MIDNIGHT).debt(midnightId, user); - require(assets >= minRollableAssets || assets == debtAssets, RollableAssetsTooLow()); + require(assets >= minRollableAssets || assets == debtAssets, RolledAssetsTooLow()); // Round in favor of the Midnight position. Thus, splitting the rolls can raise the blue final LTV. This is // mitigated by the min rollable debt. diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index d7a7bd1b4..673380f53 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -17,7 +17,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { error NotBlue(); error NotConfigured(); error NotStarted(); - error RollableAssetsTooLow(); + error RolledAssetsTooLow(); error Unauthorized(); // forgefmt: disable-start diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index ea66d287f..758319abf 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -818,7 +818,7 @@ contract BlueFallbackRollingTest is BaseTest { } function testRollRevertsForAssetsBelowMinRollableAssets() public { - vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.expectRevert(IBlueFallbackRolling.RolledAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -867,7 +867,7 @@ contract BlueFallbackRollingTest is BaseTest { true ); - vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.expectRevert(IBlueFallbackRolling.RolledAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -899,7 +899,7 @@ contract BlueFallbackRollingTest is BaseTest { true ); - vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.expectRevert(IBlueFallbackRolling.RolledAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -996,7 +996,7 @@ contract BlueFallbackRollingTest is BaseTest { DEBT - remainder ); - vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.expectRevert(IBlueFallbackRolling.RolledAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, @@ -1071,7 +1071,7 @@ contract BlueFallbackRollingTest is BaseTest { ); uint256 totalCollateralAssets = midnight.collateral(toId(midnightMarket), borrower, blueCollateralIndex); - vm.expectRevert(IBlueFallbackRolling.RollableAssetsTooLow.selector); + vm.expectRevert(IBlueFallbackRolling.RolledAssetsTooLow.selector); vm.prank(keeper); fallbackContract.roll( midnightMarket, From b5d2d62f9f2c652c21f6da8336ce867de2fc21f2 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 13:36:42 +0000 Subject: [PATCH 093/159] Add Certora spec: realizable bad debt cannot increase without price update Proves the issue #109 wish-list item. Adds a realizableBadDebt view to MidnightWrapper mirroring the badDebt computation in liquidate, plus RealizableBadDebt.spec/.conf with two rules: realizableBadDebtCannotIncrease (parametric, excludes liquidate) and liquidateRealizesBadDebt. --- certora/confs/RealizableBadDebt.conf | 29 ++++ certora/helpers/MidnightWrapper.sol | 35 ++++- certora/specs/RealizableBadDebt.spec | 223 +++++++++++++++++++++++++++ 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 certora/confs/RealizableBadDebt.conf create mode 100644 certora/specs/RealizableBadDebt.spec diff --git a/certora/confs/RealizableBadDebt.conf b/certora/confs/RealizableBadDebt.conf new file mode 100644 index 000000000..df2e0984e --- /dev/null +++ b/certora/confs/RealizableBadDebt.conf @@ -0,0 +1,29 @@ +{ + "files": [ + "certora/helpers/MidnightWrapper.sol", + "certora/helpers/Utils.sol" + ], + "parametric_contracts": [ + "MidnightWrapper" + ], + "verify": "MidnightWrapper:certora/specs/RealizableBadDebt.spec", + "solc": "solc-0.8.34", + "solc_via_ir": true, + "solc_evm_version": "osaka", + "optimistic_loop": true, + "loop_iter": 2, + "optimistic_hashing": true, + "hashing_length_bound": 2048, + "prover_args": [ + "-destructiveOptimizations twostage", + "-backendStrategy singleRace", + "-smt_useLIA false", + "-smt_useNIA true", + "-depth 0", + "-mediumTimeout 60", + "-timeout 7200", + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10}]" + ], + "smt_timeout": 7200, + "msg": "Midnight: realizable bad debt" +} diff --git a/certora/helpers/MidnightWrapper.sol b/certora/helpers/MidnightWrapper.sol index 2cb6432d3..713ac754b 100644 --- a/certora/helpers/MidnightWrapper.sol +++ b/certora/helpers/MidnightWrapper.sol @@ -6,7 +6,7 @@ import {Midnight} from "../../src/Midnight.sol"; import {Position, CollateralParams, Market} from "../../src/interfaces/IMidnight.sol"; import {IOracle} from "../../src/interfaces/IOracle.sol"; import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; -import {ORACLE_PRICE_SCALE, WAD} from "../../src/libraries/ConstantsLib.sol"; +import {ORACLE_PRICE_SCALE, WAD, maxLif} from "../../src/libraries/ConstantsLib.sol"; contract MidnightWrapper is Midnight { using UtilsLib for uint256; @@ -30,4 +30,37 @@ contract MidnightWrapper is Midnight { } return maxDebt >= debt; } + + /* This realizableBadDebt function recomputes, verbatim, the `badDebt` local that + * liquidate() computes at src/Midnight.sol:643-657, so that the prover can equate this + * getter's result with liquidate's inlined bad-debt computation. + * + * realizableBadDebt(id, borrower) + * = zeroFloorSub(debt, SUM over active-collateral i of + * ceil(ceil(collateral_i * price_i / ORACLE_PRICE_SCALE) * WAD / maxLif_i)). + * + * The maxDebt accumulation and the liquidatedCollatPrice capture from the production loop + * are intentionally omitted: neither influences badDebt. Every other operation on the + * badDebt value (msb, mulDivUp, mulDivUp, maxLif, zeroFloorSub, clearBit) is kept in the + * exact same order as production so the summarized ghosts line up 1:1. + * + * `id` is taken explicitly (mirroring isHealthyNoBitmap) and must be the id derived from + * `market`; the caller passes the matching Market, exactly as liquidate does. */ + function realizableBadDebt(Market memory market, bytes32 id, address borrower) public view returns (uint256) { + Position storage _position = position[id][borrower]; + uint256 badDebt = _position.debt; + uint128 _collateralBitmap = _position.collateralBitmap; + while (_collateralBitmap != 0) { + uint256 i = UtilsLib.msb(_collateralBitmap); + CollateralParams memory _collateralParam = market.collateralParams[i]; + uint256 price = IOracle(_collateralParam.oracle).price(); + uint256 _collateral = _position.collateral[i]; + badDebt = badDebt.zeroFloorSub( + _collateral.mulDivUp(price, ORACLE_PRICE_SCALE) + .mulDivUp(WAD, maxLif(_collateralParam.lltv, _collateralParam.liquidationCursor)) + ); + _collateralBitmap = _collateralBitmap.clearBit(i); + } + return badDebt; + } } diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec new file mode 100644 index 000000000..24abd370f --- /dev/null +++ b/certora/specs/RealizableBadDebt.spec @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association + +// Property (issue #109): +// "realizableBadDebt cannot increase (without a price update). Liquidation is a special +// case: it is not enough that it does not increase realizableBadDebt, it also realizes it." +// +// realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of +// Midnight.liquidate (src/Midnight.sol:643-657): +// zeroFloorSub(debt, SUM over active-collateral i of ceil(ceil(col_i*price_i/OPS)*WAD/maxLif_i)). +// It is exposed by MidnightWrapper.realizableBadDebt(market, id, borrower), whose loop is a +// verbatim copy of that production loop so the prover can equate the getter with liquidate's +// inlined computation (the same "match the spec's check against the code" trick used in +// Healthiness.spec for isHealthy()). +// +// "Without a price update" is modelled by summarizing _.price() as PER_CALLEE_CONSTANT: each +// oracle returns a single deterministic value fixed across the whole rule, so the before- and +// after-snapshots of the getter (and liquidate's own loop) all observe the same prices. + +import "BitmapSummaries.spec"; + +using Utils as Utils; + +methods { + function multicall(bytes[]) external => HAVOC_ALL DELETE; + + // The getter added to MidnightWrapper. Modelled envfree exactly like isHealthyNoBitmap, + // which also takes a Market and calls IOracle.price(); envfree works because price() is + // summarized and the body has no env dependency. + function realizableBadDebt(Midnight.Market, bytes32, address) external returns (uint256) envfree; + + // Envfree public getters actually used by the rules. + function debt(bytes32, address) external returns (uint128) envfree; + function totalUnits(bytes32) external returns (uint128) envfree; + function lossFactor(bytes32) external returns (uint128) envfree; + function liquidationLocked(bytes32, address) external returns (bool) envfree; + function tickSpacing(bytes32) external returns (uint8) envfree; + function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; + + // "Without price update": each oracle's price is a deterministic constant for the whole + // rule, so it is identical across the before/after evaluations of the getter and liquidate. + function _.price() external => PER_CALLEE_CONSTANT; + + // toId is linked to state via the deterministic (and, under optimistic_hashing, injective) + // keccak hash of the market, mirroring LossFactor.spec. liquidate's internal touchMarket -> + // toId(market) therefore yields the same id used to query the getter and the getters. + function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); + function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; + function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; + + // mulDiv summarized by deterministic ghosts so both bad-debt evaluations use identical + // arithmetic. Axioms are the subset of the MulDiv.spec bundle used by Healthiness.spec. + function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); + function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); + + // maxLif recomputed on the fly from (lltv, liquidationCursor); summarized deterministically + // like Healthiness.spec:30. The bound lltv*maxLif <= WAD*WAD is required in the rules. + function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); + + // Token transfers bypassed (LossFactor.spec style). All other external calls (oracle aside) + // are assumed non-reentrant / non-reverting: we reason about the function bodies, and + // liquidate is non-reentrant. + function SafeTransferLib.safeTransfer(address, address, uint256) internal => NONDET; + function SafeTransferLib.safeTransferFrom(address, address, address, uint256) internal => NONDET; + + // take's external staticcall view gates/ratifier. These run after touchMarket and cannot + // affect realizableBadDebt, but left unresolved they trigger full-storage HAVOCs that time + // the parametric rule out to UNKNOWN, so summarize them NONDET (sound: staticcall views). + function _.isRatified(Midnight.Offer, bytes, address) external => NONDET; + function _.canIncreaseCredit(address) external => NONDET; + function _.canIncreaseDebt(address) external => NONDET; +} + +/// SUMMARIES / GHOSTS /// + +definition WAD() returns uint256 = 10 ^ 18; + +definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; + +persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; + +persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; + +persistent ghost maxLifGhost(uint256, uint256) returns uint256; + +function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { + revert(); + } + return require_uint256(ghostMulDivDown(a, b, d)); +} + +function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { + revert(); + } + return require_uint256(ghostMulDivUp(a, b, d)); +} + +// toId summary: deterministic hash of the market (injective under optimistic_hashing). +function summaryToId(Midnight.Market market) returns (bytes32) { + return Utils.hashMarket(market); +} + +function marketIsCreated(Midnight.Market market) returns (bool) { + return tickSpacing(summaryToId(market)) > 0; +} + +/* Axioms proved in MulDiv.spec / ExactMath.spec (same bundle as Healthiness.spec). */ + +/* proved in mulDivZero */ +definition axiomDownZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivDown(0, b, d) == 0; + +/* proved in mulDivMonotoneA */ +definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); + +definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); + +/* proved in mulDivMonotoneB */ +definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); + +/* proved in mulDivMonotoneD */ +definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d1) >= ghostMulDivUp(a, b, d2); + +/* proved in ExactMath.spec (mulDivLifLLTV): the healthy => rbd == 0 bridge */ +definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif); + +/// RULES /// + +// (i) PARAMETRIC: no non-liquidate, non-view function may INCREASE realizableBadDebt. +// liquidate is excluded (handled by rule (ii)); view functions cannot mutate state. +// "Without price update" is enforced by the PER_CALLEE_CONSTANT price summary. +// +// FLAG (needs prover iteration): for debt-increasing functions (borrow) or collateral-removing +// functions (withdrawCollateral), rbd does not increase only because those functions re-check +// isHealthy(), and healthy => rbd == 0 (issue-#109 analysis part C). That bridge relies on +// the maxLif<=1/lltv require + axiomLifLLTV below. If the prover cannot connect f's own health check to the +// getter here (this rule does NOT re-assert isHealthy), those methods may report violations +// and this rule likely needs the Healthiness.spec global-market + isHealthyOrLiquidationLocked +// machinery grafted in (fix a global market/id/borrower, assert healthy-or-locked after f). +rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) filtered { f -> !f.isView && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector } { + bytes32 id = summaryToId(market); + + // Bound the collateral loop like Healthiness.spec does (globalMarketCollateralLength <= 2) + // so loop_iter = 2 fully unrolls both getter evaluations. + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + + // mulDiv monotonicity bundle (threaded via require forall, as Healthiness.spec does). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; + require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; + require forall mathint b. forall mathint d. axiomDownZero(b, d), "axiom"; + + // maxLif <= 1/lltv for every (lltv, cursor); proved in lifTimesLltvIsLessThanOrEqualToOne + // (ExactMath.spec). Needed for the healthy => realizableBadDebt == 0 bridge. + require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; + + uint256 rbdBefore = realizableBadDebt(market, id, borrower); + + f(e, args); + + uint256 rbdAfter = realizableBadDebt(market, id, borrower); + + assert rbdAfter <= rbdBefore, "no non-liquidate function increases realizable bad debt"; +} + +// (ii) LIQUIDATE special case: liquidate does not increase realizableBadDebt AND, when there was +// bad debt (rbdBefore > 0), it realizes it: totalUnits drops by EXACTLY rbdBefore and lossFactor +// strictly increases. +// +// The exactness rests on rbdBefore == liquidate's own `badDebt` local: the getter and liquidate's +// inlined loop run over the same PRE-call state with the same price / maxLif / mulDiv ghosts and +// bitmap summaries, so the prover equates them. liquidate then does, at src/Midnight.sol:667-673, +// `_position.debt -= badDebt` and `_marketState.totalUnits -= badDebt`; the seize/repay block +// (682-715) never touches totalUnits or lossFactor, so the drop is exactly badDebt. +rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + bytes32 id = summaryToId(market); + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require marketIsCreated(market), "market must be created (tickSpacing > 0)"; + + // Well-formedness the realization arithmetic assumes (mirrors LossFactor.spec). + require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits (totalUnitsEqualsSumNegativeDebtPlusWithdrawable)"; + + // mulDiv monotonicity bundle (threaded via require forall, as Healthiness.spec does). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; + require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; + require forall mathint b. forall mathint d. axiomDownZero(b, d), "axiom"; + require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; + + uint256 rbdBefore = realizableBadDebt(market, id, borrower); + uint256 totalUnitsBefore = totalUnits(id); + uint128 lossFactorBefore = lossFactor(id); + + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + + uint256 rbdAfter = realizableBadDebt(market, id, borrower); + + // (a) liquidate never increases realizable bad debt. + // FLAG: this direction recomputes rbd over POST state (debt reduced by badDebt and possibly + // repaidUnits, collateral seized). It leans on the mulDiv monotonicity axioms and is the + // fiddly part; if it does not go through, first prove it for the pure-realization path + // (seizedAssets == 0 && repaidUnits == 0), as LossFactor.spec's liquidate rule does. + assert rbdAfter <= rbdBefore, "liquidate does not increase realizable bad debt"; + + // (b) if there was bad debt, it is realized in totalUnits by EXACTLY rbdBefore. + assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore), "bad debt realized: totalUnits drops by exactly rbdBefore"; + + // (c) and lossFactor strictly increases. + // FLAG: strict `>` may need a strict-monotonicity axiom for mulDivDown that is not in the + // bundle above (the ghost only carries non-strict monotonicity). LossFactor.spec proves the + // weaker `lossFactor changed <=> totalUnits decreased`. If strictness fails, fall back to + // `lossFactor(id) != lossFactorBefore`. + assert rbdBefore > 0 => lossFactor(id) > lossFactorBefore, "lossFactor strictly increases when bad debt is realized"; +} From 9a50fa98e6e94e6233d4d446bd08753b7c48a04d Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 24 Jul 2026 15:51:36 +0200 Subject: [PATCH 094/159] Apply suggestion from @MathisGD Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- certora/specs/RealizableBadDebt.spec | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 24abd370f..29b82d02c 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -3,19 +3,12 @@ // Property (issue #109): // "realizableBadDebt cannot increase (without a price update). Liquidation is a special -// case: it is not enough that it does not increase realizableBadDebt, it also realizes it." +// case: it should realize the bad debt and leave zero." // // realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of -// Midnight.liquidate (src/Midnight.sol:643-657): -// zeroFloorSub(debt, SUM over active-collateral i of ceil(ceil(col_i*price_i/OPS)*WAD/maxLif_i)). -// It is exposed by MidnightWrapper.realizableBadDebt(market, id, borrower), whose loop is a -// verbatim copy of that production loop so the prover can equate the getter with liquidate's -// inlined computation (the same "match the spec's check against the code" trick used in -// Healthiness.spec for isHealthy()). +// Midnight.liquidate (src/Midnight.sol:643-657). // -// "Without a price update" is modelled by summarizing _.price() as PER_CALLEE_CONSTANT: each -// oracle returns a single deterministic value fixed across the whole rule, so the before- and -// after-snapshots of the getter (and liquidate's own loop) all observe the same prices. +// "Without a price update" is modelled by summarizing _.price() as PER_CALLEE_CONSTANT. import "BitmapSummaries.spec"; From e003af3ef2d39a2ffb824d290fe4836e9765adb0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 14:14:24 +0000 Subject: [PATCH 095/159] Fix RealizableBadDebt rules: health bridge for take/withdrawCollateral, leave-zero for liquidate --- certora/helpers/MidnightWrapper.sol | 25 ++-- certora/specs/RealizableBadDebt.spec | 181 ++++++++++++++------------- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/certora/helpers/MidnightWrapper.sol b/certora/helpers/MidnightWrapper.sol index 713ac754b..41b836f28 100644 --- a/certora/helpers/MidnightWrapper.sol +++ b/certora/helpers/MidnightWrapper.sol @@ -31,21 +31,16 @@ contract MidnightWrapper is Midnight { return maxDebt >= debt; } - /* This realizableBadDebt function recomputes, verbatim, the `badDebt` local that - * liquidate() computes at src/Midnight.sol:643-657, so that the prover can equate this - * getter's result with liquidate's inlined bad-debt computation. - * - * realizableBadDebt(id, borrower) - * = zeroFloorSub(debt, SUM over active-collateral i of - * ceil(ceil(collateral_i * price_i / ORACLE_PRICE_SCALE) * WAD / maxLif_i)). - * - * The maxDebt accumulation and the liquidatedCollatPrice capture from the production loop - * are intentionally omitted: neither influences badDebt. Every other operation on the - * badDebt value (msb, mulDivUp, mulDivUp, maxLif, zeroFloorSub, clearBit) is kept in the - * exact same order as production so the summarized ghosts line up 1:1. - * - * `id` is taken explicitly (mirroring isHealthyNoBitmap) and must be the id derived from - * `market`; the caller passes the matching Market, exactly as liquidate does. */ + // This realizableBadDebt function recomputes, verbatim, the badDebt local that + // liquidate() computes at src/Midnight.sol:643-657, so that the prover can equate this + // getter's result with liquidate's inlined bad-debt computation. + // + // realizableBadDebt(id, borrower) + // = zeroFloorSub(debt, SUM over active-collateral i of + // ceil(ceil(collateral_i * price_i / ORACLE_PRICE_SCALE) * WAD / maxLif_i)). + // + // id is taken explicitly (mirroring isHealthyNoBitmap) and must be the id derived from + // market; the caller passes the matching Market, exactly as liquidate does. function realizableBadDebt(Market memory market, bytes32 id, address borrower) public view returns (uint256) { Position storage _position = position[id][borrower]; uint256 badDebt = _position.debt; diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 29b82d02c..eaf33fff9 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -17,12 +17,7 @@ using Utils as Utils; methods { function multicall(bytes[]) external => HAVOC_ALL DELETE; - // The getter added to MidnightWrapper. Modelled envfree exactly like isHealthyNoBitmap, - // which also takes a Market and calls IOracle.price(); envfree works because price() is - // summarized and the body has no env dependency. function realizableBadDebt(Midnight.Market, bytes32, address) external returns (uint256) envfree; - - // Envfree public getters actually used by the rules. function debt(bytes32, address) external returns (uint128) envfree; function totalUnits(bytes32) external returns (uint128) envfree; function lossFactor(bytes32) external returns (uint128) envfree; @@ -30,38 +25,27 @@ methods { function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - // "Without price update": each oracle's price is a deterministic constant for the whole - // rule, so it is identical across the before/after evaluations of the getter and liquidate. function _.price() external => PER_CALLEE_CONSTANT; - // toId is linked to state via the deterministic (and, under optimistic_hashing, injective) - // keccak hash of the market, mirroring LossFactor.spec. liquidate's internal touchMarket -> - // toId(market) therefore yields the same id used to query the getter and the getters. function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; - // mulDiv summarized by deterministic ghosts so both bad-debt evaluations use identical - // arithmetic. Axioms are the subset of the MulDiv.spec bundle used by Healthiness.spec. function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); - - // maxLif recomputed on the fly from (lltv, liquidationCursor); summarized deterministically - // like Healthiness.spec:30. The bound lltv*maxLif <= WAD*WAD is required in the rules. function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); - // Token transfers bypassed (LossFactor.spec style). All other external calls (oracle aside) - // are assumed non-reentrant / non-reverting: we reason about the function bodies, and - // liquidate is non-reentrant. + // All external calls are assumed non-reentrant / non-reverting: we reason about the function bodies for safety properties. function SafeTransferLib.safeTransfer(address, address, uint256) internal => NONDET; function SafeTransferLib.safeTransferFrom(address, address, address, uint256) internal => NONDET; - - // take's external staticcall view gates/ratifier. These run after touchMarket and cannot - // affect realizableBadDebt, but left unresolved they trigger full-storage HAVOCs that time - // the parametric rule out to UNKNOWN, so summarize them NONDET (sound: staticcall views). function _.isRatified(Midnight.Offer, bytes, address) external => NONDET; function _.canIncreaseCredit(address) external => NONDET; function _.canIncreaseDebt(address) external => NONDET; + function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; + function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; + function _.onRepay(bytes32, Midnight.Market, uint256, address, bytes) external => NONDET; + function _.onLiquidate(address, bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes, uint256) external => NONDET; + function _.onFlashLoan(address, address[], uint256[], bytes) external => NONDET; } /// SUMMARIES / GHOSTS /// @@ -92,7 +76,6 @@ function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { return require_uint256(ghostMulDivUp(a, b, d)); } -// toId summary: deterministic hash of the market (injective under optimistic_hashing). function summaryToId(Midnight.Market market) returns (bytes32) { return Utils.hashMarket(market); } @@ -101,56 +84,37 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } -/* Axioms proved in MulDiv.spec / ExactMath.spec (same bundle as Healthiness.spec). */ - -/* proved in mulDivZero */ -definition axiomDownZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivDown(0, b, d) == 0; - -/* proved in mulDivMonotoneA */ definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); -/* proved in mulDivMonotoneB */ definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); -/* proved in mulDivMonotoneD */ definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d1) >= ghostMulDivUp(a, b, d2); -/* proved in ExactMath.spec (mulDivLifLLTV): the healthy => rbd == 0 bridge */ +definition axiomDownZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivDown(0, b, d) == 0; + +definition axiomUpGeqDown(mathint a, mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d); + definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif); /// RULES /// -// (i) PARAMETRIC: no non-liquidate, non-view function may INCREASE realizableBadDebt. -// liquidate is excluded (handled by rule (ii)); view functions cannot mutate state. -// "Without price update" is enforced by the PER_CALLEE_CONSTANT price summary. -// -// FLAG (needs prover iteration): for debt-increasing functions (borrow) or collateral-removing -// functions (withdrawCollateral), rbd does not increase only because those functions re-check -// isHealthy(), and healthy => rbd == 0 (issue-#109 analysis part C). That bridge relies on -// the maxLif<=1/lltv require + axiomLifLLTV below. If the prover cannot connect f's own health check to the -// getter here (this rule does NOT re-assert isHealthy), those methods may report violations -// and this rule likely needs the Healthiness.spec global-market + isHealthyOrLiquidationLocked -// machinery grafted in (fix a global market/id/borrower, assert healthy-or-locked after f). -rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) filtered { f -> !f.isView && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector } { +// No non-liquidate, non-view function that removes collateral or raises debt (take, +// withdrawCollateral) may increase realizableBadDebt of an arbitrary position. Those three are +// excluded here and handled by dedicated rules below. +rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) +filtered { + f -> !f.isView + && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector + && f.selector != sig:take(Midnight.Offer, bytes, uint256, address, address, address, bytes).selector + && f.selector != sig:withdrawCollateral(Midnight.Market, uint256, uint256, address, address).selector +} { bytes32 id = summaryToId(market); - // Bound the collateral loop like Healthiness.spec does (globalMarketCollateralLength <= 2) - // so loop_iter = 2 fully unrolls both getter evaluations. require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - // mulDiv monotonicity bundle (threaded via require forall, as Healthiness.spec does). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; - require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; - require forall mathint b. forall mathint d. axiomDownZero(b, d), "axiom"; - - // maxLif <= 1/lltv for every (lltv, cursor); proved in lifTimesLltvIsLessThanOrEqualToOne - // (ExactMath.spec). Needed for the healthy => realizableBadDebt == 0 bridge. - require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; uint256 rbdBefore = realizableBadDebt(market, id, borrower); @@ -158,29 +122,67 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight uint256 rbdAfter = realizableBadDebt(market, id, borrower); - assert rbdAfter <= rbdBefore, "no non-liquidate function increases realizable bad debt"; + assert rbdAfter <= rbdBefore; } -// (ii) LIQUIDATE special case: liquidate does not increase realizableBadDebt AND, when there was -// bad debt (rbdBefore > 0), it realizes it: totalUnits drops by EXACTLY rbdBefore and lossFactor -// strictly increases. -// -// The exactness rests on rbdBefore == liquidate's own `badDebt` local: the getter and liquidate's -// inlined loop run over the same PRE-call state with the same price / maxLif / mulDiv ghosts and -// bitmap summaries, so the prover equates them. liquidate then does, at src/Midnight.sol:667-673, -// `_position.debt -= badDebt` and `_marketState.totalUnits -= badDebt`; the seize/repay block -// (682-715) never touches totalUnits or lossFactor, so the drop is exactly badDebt. +// withdrawCollateral removes collateral but requires the borrower to be healthy afterwards +// (src/Midnight.sol:606), and a healthy borrower has zero realizable bad debt (lltv * maxLif <= +// WAD * WAD, via axiomLifLLTV). Measuring on the acted-on (market, id, onBehalf) closes it. +rule withdrawCollateralDoesNotIncreaseRealizableBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 assets, address onBehalf, address receiver) { + bytes32 id = summaryToId(market); + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; + require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; + require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; + + uint256 rbdBefore = realizableBadDebt(market, id, onBehalf); + + withdrawCollateral(e, market, collateralIndex, assets, onBehalf, receiver); + + uint256 rbdAfter = realizableBadDebt(market, id, onBehalf); + + assert rbdAfter <= rbdBefore; +} + +// take may raise the seller's debt but requires the seller to be healthy or liquidation-locked +// afterwards (src/Midnight.sol:512). Scoping out the locked seller (only reachable re-entrantly) +// leaves the healthy branch, and a healthy borrower has zero realizable bad debt. +rule takeDoesNotIncreaseRealizableBadDebt(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { + bytes32 id = summaryToId(offer.market); + address seller = offer.buy ? offer.maker : taker; + + require offer.market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require !liquidationLocked(id, seller), "scope out the locked (re-entrant) seller case"; + + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; + require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; + require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; + + uint256 rbdBefore = realizableBadDebt(offer.market, id, seller); + + take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); + + uint256 rbdAfter = realizableBadDebt(offer.market, id, seller); + + assert rbdAfter <= rbdBefore; +} + +// liquidate never increases realizable bad debt, and when there is bad debt it realizes it: the +// getter equals liquidate's own badDebt local (same pre-state, price, maxLif and mulDiv ghosts), +// and liquidate drops totalUnits by exactly that amount (src/Midnight.sol:673); the seize/repay +// block never touches totalUnits. rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - - // Well-formedness the realization arithmetic assumes (mirrors LossFactor.spec). require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits (totalUnitsEqualsSumNegativeDebtPlusWithdrawable)"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - // mulDiv monotonicity bundle (threaded via require forall, as Healthiness.spec does). require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; @@ -191,26 +193,31 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI uint256 rbdBefore = realizableBadDebt(market, id, borrower); uint256 totalUnitsBefore = totalUnits(id); - uint128 lossFactorBefore = lossFactor(id); liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); uint256 rbdAfter = realizableBadDebt(market, id, borrower); - // (a) liquidate never increases realizable bad debt. - // FLAG: this direction recomputes rbd over POST state (debt reduced by badDebt and possibly - // repaidUnits, collateral seized). It leans on the mulDiv monotonicity axioms and is the - // fiddly part; if it does not go through, first prove it for the pure-realization path - // (seizedAssets == 0 && repaidUnits == 0), as LossFactor.spec's liquidate rule does. - assert rbdAfter <= rbdBefore, "liquidate does not increase realizable bad debt"; - - // (b) if there was bad debt, it is realized in totalUnits by EXACTLY rbdBefore. - assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore), "bad debt realized: totalUnits drops by exactly rbdBefore"; - - // (c) and lossFactor strictly increases. - // FLAG: strict `>` may need a strict-monotonicity axiom for mulDivDown that is not in the - // bundle above (the ghost only carries non-strict monotonicity). LossFactor.spec proves the - // weaker `lossFactor changed <=> totalUnits decreased`. If strictness fails, fall back to - // `lossFactor(id) != lossFactorBefore`. - assert rbdBefore > 0 => lossFactor(id) > lossFactorBefore, "lossFactor strictly increases when bad debt is realized"; + assert rbdAfter <= rbdBefore; + assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); +} + +// On the pure realization path (seizedAssets == 0 and repaidUnits == 0) liquidate only reduces +// debt by badDebt and leaves collateral untouched, so the recomputed realizable bad debt is zero. +rule liquidateLeavesZeroBadDebt(env e, Midnight.Market market, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + bytes32 id = summaryToId(market); + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require marketIsCreated(market), "market must be created (tickSpacing > 0)"; + require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + + uint256 rbdBefore = realizableBadDebt(market, id, borrower); + require rbdBefore > 0, "there is bad debt to realize"; + + liquidate(e, market, 0, 0, 0, borrower, postMaturityMode, receiver, callback, data); + + uint256 rbdAfter = realizableBadDebt(market, id, borrower); + + assert rbdAfter == 0; } From 94466259faa620018c0eeddca2691fba05110655 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 14:30:53 +0000 Subject: [PATCH 096/159] Tighten mulDiv ghosts in liquidateRealizesBadDebt to close seize-path counterexample --- certora/specs/RealizableBadDebt.spec | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index eaf33fff9..ac0c8c0b2 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -191,6 +191,14 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require forall mathint b. forall mathint d. axiomDownZero(b, d), "axiom"; require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; + // Tight floor/ceil characterizations (proven in MulDiv.spec, matching LiquidationBoundedByLIF.spec). + // Confined to this rule so the seize-path arithmetic is pinned down without adding nonlinear cost to + // the other rules' cheap ghosts. + require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivDown(a, b, d) * d <= a * b, "axiom"; + require forall mathint a. forall mathint b. forall mathint d. d > 0 => (ghostMulDivDown(a, b, d) + 1) * d > a * b, "axiom"; + require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) * d >= a * b, "axiom"; + require forall mathint a. forall mathint b. forall mathint d. d > 0 && ghostMulDivUp(a, b, d) > 0 => (ghostMulDivUp(a, b, d) - 1) * d < a * b, "axiom"; + uint256 rbdBefore = realizableBadDebt(market, id, borrower); uint256 totalUnitsBefore = totalUnits(id); From d0051d26815ade1740d87acfcc29f0130f15b1d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 15:06:16 +0000 Subject: [PATCH 097/159] Prove mulDivUp >= mulDivDown in MulDiv.spec --- certora/specs/MulDiv.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 7df127a4d..2c3b2e783 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -121,6 +121,10 @@ rule mulDivUpRoundsUp(uint256 a, uint256 b, uint256 d) { assert mulDivUp(a, b, d) * d >= a * b; } +rule mulDivUpGeqMulDivDown(uint256 a, uint256 b, uint256 d) { + assert mulDivUp(a, b, d) >= mulDivDown(a, b, d); +} + rule mulDivUpTightBound(uint256 a, uint256 b, uint256 d) { assert mulDivUp(a, b, d) > 0 => (mulDivUp(a, b, d) - 1) * d < a * b; } From bfe5d111809266627c290c2896267d5804de0301 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 15:32:38 +0000 Subject: [PATCH 098/159] Merge take/withdrawCollateral into parametric rule; assert liquidate leaves zero bad debt --- certora/specs/RealizableBadDebt.spec | 95 ++++------------------------ 1 file changed, 12 insertions(+), 83 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index ac0c8c0b2..27f2b9a57 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -100,81 +100,32 @@ definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a > /// RULES /// -// No non-liquidate, non-view function that removes collateral or raises debt (take, -// withdrawCollateral) may increase realizableBadDebt of an arbitrary position. Those three are -// excluded here and handled by dedicated rules below. -rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) -filtered { - f -> !f.isView - && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector - && f.selector != sig:take(Midnight.Offer, bytes, uint256, address, address, address, bytes).selector - && f.selector != sig:withdrawCollateral(Midnight.Market, uint256, uint256, address, address).selector -} { +// No non-liquidate, non-view function may increase realizableBadDebt of an arbitrary position. +// take and withdrawCollateral both require the acted-on borrower healthy afterwards, and a healthy +// borrower has zero realizable bad debt (via the health-bridge axioms below); the locked seller +// (only reachable re-entrantly) is scoped out. +rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) filtered { f -> !f.isView && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector } { bytes32 id = summaryToId(market); require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - - uint256 rbdBefore = realizableBadDebt(market, id, borrower); - - f(e, args); - - uint256 rbdAfter = realizableBadDebt(market, id, borrower); - - assert rbdAfter <= rbdBefore; -} - -// withdrawCollateral removes collateral but requires the borrower to be healthy afterwards -// (src/Midnight.sol:606), and a healthy borrower has zero realizable bad debt (lltv * maxLif <= -// WAD * WAD, via axiomLifLLTV). Measuring on the acted-on (market, id, onBehalf) closes it. -rule withdrawCollateralDoesNotIncreaseRealizableBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 assets, address onBehalf, address receiver) { - bytes32 id = summaryToId(market); - - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; - require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; - require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; - - uint256 rbdBefore = realizableBadDebt(market, id, onBehalf); - - withdrawCollateral(e, market, collateralIndex, assets, onBehalf, receiver); - - uint256 rbdAfter = realizableBadDebt(market, id, onBehalf); - - assert rbdAfter <= rbdBefore; -} - -// take may raise the seller's debt but requires the seller to be healthy or liquidation-locked -// afterwards (src/Midnight.sol:512). Scoping out the locked seller (only reachable re-entrantly) -// leaves the healthy branch, and a healthy borrower has zero realizable bad debt. -rule takeDoesNotIncreaseRealizableBadDebt(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { - bytes32 id = summaryToId(offer.market); - address seller = offer.buy ? offer.maker : taker; - - require offer.market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require !liquidationLocked(id, seller), "scope out the locked (re-entrant) seller case"; + require !liquidationLocked(id, borrower), "scope out the locked (re-entrant) seller case"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; - uint256 rbdBefore = realizableBadDebt(offer.market, id, seller); + uint256 rbdBefore = realizableBadDebt(market, id, borrower); - take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); + f(e, args); - uint256 rbdAfter = realizableBadDebt(offer.market, id, seller); + uint256 rbdAfter = realizableBadDebt(market, id, borrower); assert rbdAfter <= rbdBefore; } -// liquidate never increases realizable bad debt, and when there is bad debt it realizes it: the -// getter equals liquidate's own badDebt local (same pre-state, price, maxLif and mulDiv ghosts), -// and liquidate drops totalUnits by exactly that amount (src/Midnight.sol:673); the seize/repay -// block never touches totalUnits. +// liquidate realizes bad debt: it recomputes to zero and drops totalUnits by exactly the realized +// bad debt (src/Midnight.sol:673); the seize/repay block never touches totalUnits. rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -192,8 +143,6 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; // Tight floor/ceil characterizations (proven in MulDiv.spec, matching LiquidationBoundedByLIF.spec). - // Confined to this rule so the seize-path arithmetic is pinned down without adding nonlinear cost to - // the other rules' cheap ghosts. require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivDown(a, b, d) * d <= a * b, "axiom"; require forall mathint a. forall mathint b. forall mathint d. d > 0 => (ghostMulDivDown(a, b, d) + 1) * d > a * b, "axiom"; require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) * d >= a * b, "axiom"; @@ -206,26 +155,6 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI uint256 rbdAfter = realizableBadDebt(market, id, borrower); - assert rbdAfter <= rbdBefore; - assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); -} - -// On the pure realization path (seizedAssets == 0 and repaidUnits == 0) liquidate only reduces -// debt by badDebt and leaves collateral untouched, so the recomputed realizable bad debt is zero. -rule liquidateLeavesZeroBadDebt(env e, Midnight.Market market, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { - bytes32 id = summaryToId(market); - - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - - uint256 rbdBefore = realizableBadDebt(market, id, borrower); - require rbdBefore > 0, "there is bad debt to realize"; - - liquidate(e, market, 0, 0, 0, borrower, postMaturityMode, receiver, callback, data); - - uint256 rbdAfter = realizableBadDebt(market, id, borrower); - assert rbdAfter == 0; + assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); } From eed485c7f0c60bff1081d4ce27aea60a5cf3d085 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 17:58:14 +0000 Subject: [PATCH 099/159] Help prover on liquidateRealizesBadDebt: import LIF seize bound + split asserts Import the seize/repay bound proven in LiquidationBoundedByLIF.spec as a backed assumption so the solver need not re-derive it through the branchy nonlinear liquidate body. Split the cheap totalUnits realization assert into its own rule so the hard rbdAfter==0 obligation gets the full solver budget. Inline the post-liquidation value into the assert, drop callback data, and add cvc5/bitwuzla to the solver race. --- certora/confs/RealizableBadDebt.conf | 2 +- certora/specs/RealizableBadDebt.spec | 48 ++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/certora/confs/RealizableBadDebt.conf b/certora/confs/RealizableBadDebt.conf index df2e0984e..8a5da6737 100644 --- a/certora/confs/RealizableBadDebt.conf +++ b/certora/confs/RealizableBadDebt.conf @@ -22,7 +22,7 @@ "-depth 0", "-mediumTimeout 60", "-timeout 7200", - "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10}]" + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10},cvc5:def,bitwuzla:def]" ], "smt_timeout": 7200, "msg": "Midnight: realizable bad debt" diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 27f2b9a57..7fddb9845 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -25,7 +25,8 @@ methods { function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - function _.price() external => PER_CALLEE_CONSTANT; + // Per-callee constant price (no price update); named so rules can reference it, matching LiquidationBoundedByLIF.spec. + function _.price() external => summaryPrice(calledContract) expect(uint256); function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; @@ -60,6 +61,8 @@ persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; persistent ghost maxLifGhost(uint256, uint256) returns uint256; +persistent ghost summaryPrice(address) returns uint256; + function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { @@ -124,8 +127,28 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight assert rbdAfter <= rbdBefore; } -// liquidate realizes bad debt: it recomputes to zero and drops totalUnits by exactly the realized -// bad debt (src/Midnight.sol:673); the seize/repay block never touches totalUnits. +// liquidate drops totalUnits by exactly the realized bad debt (src/Midnight.sol:673); the +// seize/repay block never touches totalUnits. Cheap: the badDebt local is recomputed by the +// getter verbatim, so no mulDiv axioms are needed to equate them. +rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + bytes32 id = summaryToId(market); + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require marketIsCreated(market), "market must be created (tickSpacing > 0)"; + require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + + uint256 rbdBefore = realizableBadDebt(market, id, borrower); + uint256 totalUnitsBefore = totalUnits(id); + + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + + assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); +} + +// liquidate realizes the bad debt: it recomputes to zero. The seize bound proven in +// LiquidationBoundedByLIF.spec (imported below as a backed assumption) shows removing the seized +// collateral, valued at maxLif, drops the maxLif-collateral-sum by at most the repaid debt. rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -133,6 +156,11 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; + + mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); + mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); + require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant; precondition of the LIF bound)"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; @@ -148,13 +176,13 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) * d >= a * b, "axiom"; require forall mathint a. forall mathint b. forall mathint d. d > 0 && ghostMulDivUp(a, b, d) > 0 => (ghostMulDivUp(a, b, d) - 1) * d < a * b, "axiom"; - uint256 rbdBefore = realizableBadDebt(market, id, borrower); - uint256 totalUnitsBefore = totalUnits(id); + uint256 seizedResult; + uint256 repaidResult; + seizedResult, repaidResult = liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + // Seize bounded by LIF (proven in LiquidationBoundedByLIF.spec): the maxLif-value of the seized + // collateral never exceeds the repaid debt, so removing it keeps the recomputed bad debt at zero. + require seizedResult * price * WAD() <= repaidResult * ORACLE_PRICE_SCALE() * maxLif, "seize bounded by maxLif"; - uint256 rbdAfter = realizableBadDebt(market, id, borrower); - - assert rbdAfter == 0; - assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); + assert realizableBadDebt(market, id, borrower) == 0; } From 7f77776530466720df91a0cd185f61c55b0bc914 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 20:39:15 +0000 Subject: [PATCH 100/159] Isolate hard liquidate realizable-bad-debt rule with getter-form seize bound Restore RealizableBadDebt.spec to the green PER_CALLEE_CONSTANT shape: keep the parametric realizableBadDebtCannotIncrease and liquidateRealizesTotalUnits rules and the pure-path liquidateLeavesZeroBadDebt rule, and drop the full-args ==0 rule (and its cvc5/bitwuzla racers) from this spec. Prove the full-args ==0 rule in a dedicated RealizableBadDebtLiquidate.spec/conf. The getter subtracts g(c) = mulDivUp(mulDivUp(c, price, SCALE), WAD, maxLif) per collateral; the rule assumes only the near-linear ghost consequences of two MulDiv lemmas (sub-additivity mulDivAddUpUp and the new getter-form seize bound mulDivSeizeValueBounded), so the solver no longer re-derives nonlinear mulDiv. Restricted to !postMaturityMode, where the seize factor equals maxLif. --- certora/confs/RealizableBadDebt.conf | 2 +- certora/confs/RealizableBadDebtLiquidate.conf | 32 ++++ certora/specs/MulDiv.spec | 8 + certora/specs/RealizableBadDebt.spec | 51 ++---- certora/specs/RealizableBadDebtLiquidate.spec | 153 ++++++++++++++++++ 5 files changed, 204 insertions(+), 42 deletions(-) create mode 100644 certora/confs/RealizableBadDebtLiquidate.conf create mode 100644 certora/specs/RealizableBadDebtLiquidate.spec diff --git a/certora/confs/RealizableBadDebt.conf b/certora/confs/RealizableBadDebt.conf index 8a5da6737..df2e0984e 100644 --- a/certora/confs/RealizableBadDebt.conf +++ b/certora/confs/RealizableBadDebt.conf @@ -22,7 +22,7 @@ "-depth 0", "-mediumTimeout 60", "-timeout 7200", - "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10},cvc5:def,bitwuzla:def]" + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10}]" ], "smt_timeout": 7200, "msg": "Midnight: realizable bad debt" diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf new file mode 100644 index 000000000..57b8e450e --- /dev/null +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -0,0 +1,32 @@ +{ + "files": [ + "certora/helpers/MidnightWrapper.sol", + "certora/helpers/Utils.sol" + ], + "parametric_contracts": [ + "MidnightWrapper" + ], + "verify": "MidnightWrapper:certora/specs/RealizableBadDebtLiquidate.spec", + "rule": [ + "liquidateRealizesBadDebt" + ], + "solc": "solc-0.8.34", + "solc_via_ir": true, + "solc_evm_version": "osaka", + "optimistic_loop": true, + "loop_iter": 2, + "optimistic_hashing": true, + "hashing_length_bound": 2048, + "prover_args": [ + "-destructiveOptimizations twostage", + "-backendStrategy singleRace", + "-smt_useLIA false", + "-smt_useNIA true", + "-depth 0", + "-mediumTimeout 120", + "-timeout 7200", + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10},z3:def{randomSeed=11},z3:def{randomSeed=12},cvc5:def,bitwuzla:def]" + ], + "smt_timeout": 7200, + "msg": "Midnight: realizable bad debt (liquidate)" +} diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 2c3b2e783..4d76c57fa 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -96,6 +96,14 @@ rule mulDivInverseUpDown(uint256 a, uint256 b, uint256 d) { assert mulDivUp(mulDivDown(a, b, d), d, b) <= a; } +// Getter-form seize valuation bound: valuing (up-up) the collateral that liquidate seizes (down-down) +// for repaidUnits r never exceeds r, when the seize and the valuation share the same factor l. +rule mulDivSeizeValueBounded(uint256 r, uint256 l, uint256 price, uint256 wad, uint256 scale) { + require l > 0 && price > 0 && wad > 0 && scale > 0; + uint256 seized = mulDivDown(mulDivDown(r, l, wad), scale, price); + assert mulDivUp(mulDivUp(seized, price, scale), wad, l) <= r; +} + rule mulDivArgumentLesserThanDenominator(uint256 a, uint256 b, uint256 d) { assert a <= d => mulDivDown(a, b, d) <= b; assert a <= d => mulDivUp(a, b, d) <= b; diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 7fddb9845..af2bf0113 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -25,8 +25,7 @@ methods { function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - // Per-callee constant price (no price update); named so rules can reference it, matching LiquidationBoundedByLIF.spec. - function _.price() external => summaryPrice(calledContract) expect(uint256); + function _.price() external => PER_CALLEE_CONSTANT; function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; @@ -61,8 +60,6 @@ persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; persistent ghost maxLifGhost(uint256, uint256) returns uint256; -persistent ghost summaryPrice(address) returns uint256; - function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { @@ -87,16 +84,8 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } -definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); - definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); -definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); - -definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d1) >= ghostMulDivUp(a, b, d2); - -definition axiomDownZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivDown(0, b, d) == 0; - definition axiomUpGeqDown(mathint a, mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d); definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif); @@ -146,43 +135,23 @@ rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collater assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); } -// liquidate realizes the bad debt: it recomputes to zero. The seize bound proven in -// LiquidationBoundedByLIF.spec (imported below as a backed assumption) shows removing the seized -// collateral, valued at maxLif, drops the maxLif-collateral-sum by at most the repaid debt. -rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { +// On the pure realization path (seizedAssets == 0 and repaidUnits == 0) liquidate only reduces +// debt by badDebt and leaves collateral untouched, so the recomputed realizable bad debt is zero. +// The full seize/repay path is proven separately in RealizableBadDebtLiquidate.spec. +rule liquidateLeavesZeroBadDebt(env e, Midnight.Market market, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; - - mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); - mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); - require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant; precondition of the LIF bound)"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; - require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; - require forall mathint b. forall mathint d. axiomDownZero(b, d), "axiom"; - require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; - - // Tight floor/ceil characterizations (proven in MulDiv.spec, matching LiquidationBoundedByLIF.spec). - require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivDown(a, b, d) * d <= a * b, "axiom"; - require forall mathint a. forall mathint b. forall mathint d. d > 0 => (ghostMulDivDown(a, b, d) + 1) * d > a * b, "axiom"; - require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) * d >= a * b, "axiom"; - require forall mathint a. forall mathint b. forall mathint d. d > 0 && ghostMulDivUp(a, b, d) > 0 => (ghostMulDivUp(a, b, d) - 1) * d < a * b, "axiom"; + uint256 rbdBefore = realizableBadDebt(market, id, borrower); + require rbdBefore > 0, "there is bad debt to realize"; - uint256 seizedResult; - uint256 repaidResult; - seizedResult, repaidResult = liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + liquidate(e, market, 0, 0, 0, borrower, postMaturityMode, receiver, callback, data); - // Seize bounded by LIF (proven in LiquidationBoundedByLIF.spec): the maxLif-value of the seized - // collateral never exceeds the repaid debt, so removing it keeps the recomputed bad debt at zero. - require seizedResult * price * WAD() <= repaidResult * ORACLE_PRICE_SCALE() * maxLif, "seize bounded by maxLif"; + uint256 rbdAfter = realizableBadDebt(market, id, borrower); - assert realizableBadDebt(market, id, borrower) == 0; + assert rbdAfter == 0; } diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec new file mode 100644 index 000000000..7eb31d2f4 --- /dev/null +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association + +// Property (issue #109), liquidate case: +// "Liquidation realizes the bad debt and leaves zero." +// +// This is the hard, full-args counterpart of the rules in RealizableBadDebt.spec: after a +// liquidate with arbitrary seizedAssets/repaidUnits, realizableBadDebt recomputes to zero. +// It is isolated in its own spec (and CI leg) because it needs the getter-form mulDivUp +// value-drop bound, which is heavy for the solver. +// +// realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of +// Midnight.liquidate (src/Midnight.sol:643-657), and per active collateral c it subtracts +// g(c) = mulDivUp(mulDivUp(c, price, ORACLE_PRICE_SCALE), WAD, maxLif). +// Liquidate seizes from a single collateral (c_k -> c_k - seizedAssets) and repays repaidUnits. +// The proof: the getter-sum drop g(c_k) - g(c_k - seizedAssets) is at most g(seizedAssets) +// (double-mulDivUp sub-additivity), and g(seizedAssets) <= repaidUnits (seize-value bound), so +// the getter-sum drops by at most the debt drop and the recomputed bad debt stays zero. +// +// The rule is restricted to the non-post-maturity path (require !postMaturityMode), where the +// seize factor lif equals maxLif (src/Midnight.sol:685-687); the post-maturity path (lif < maxLif) +// is left for follow-up. + +import "BitmapSummaries.spec"; + +using Utils as Utils; + +methods { + function multicall(bytes[]) external => HAVOC_ALL DELETE; + + function realizableBadDebt(Midnight.Market, bytes32, address) external returns (uint256) envfree; + function debt(bytes32, address) external returns (uint128) envfree; + function totalUnits(bytes32) external returns (uint128) envfree; + function lossFactor(bytes32) external returns (uint128) envfree; + function liquidationLocked(bytes32, address) external returns (bool) envfree; + function tickSpacing(bytes32) external returns (uint8) envfree; + function collateral(bytes32, address, uint256) external returns (uint128) envfree; + function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; + + // Per-callee constant price (no price update); named so the rule can reference it, matching LiquidationBoundedByLIF.spec. + function _.price() external => summaryPrice(calledContract) expect(uint256); + + function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); + function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; + function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; + + function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); + function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); + function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); + + // All external calls are assumed non-reentrant / non-reverting: we reason about the function bodies for safety properties. + function SafeTransferLib.safeTransfer(address, address, uint256) internal => NONDET; + function SafeTransferLib.safeTransferFrom(address, address, address, uint256) internal => NONDET; + function _.isRatified(Midnight.Offer, bytes, address) external => NONDET; + function _.canIncreaseCredit(address) external => NONDET; + function _.canIncreaseDebt(address) external => NONDET; + function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; + function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; + function _.onRepay(bytes32, Midnight.Market, uint256, address, bytes) external => NONDET; + function _.onLiquidate(address, bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes, uint256) external => NONDET; + function _.onFlashLoan(address, address[], uint256[], bytes) external => NONDET; +} + +/// SUMMARIES / GHOSTS /// + +definition WAD() returns uint256 = 10 ^ 18; + +definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; + +persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; + +persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; + +persistent ghost maxLifGhost(uint256, uint256) returns uint256; + +persistent ghost summaryPrice(address) returns uint256; + +function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { + revert(); + } + return require_uint256(ghostMulDivDown(a, b, d)); +} + +function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { + revert(); + } + return require_uint256(ghostMulDivUp(a, b, d)); +} + +function summaryToId(Midnight.Market market) returns (bytes32) { + return Utils.hashMarket(market); +} + +function marketIsCreated(Midnight.Market market) returns (bool) { + return tickSpacing(summaryToId(market)) > 0; +} + +definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); + +definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(0, b, d) == 0; + +// Sub-additivity of mulDivUp (proven in MulDiv.spec as mulDivAddUpUp): ceil((a1+a2)*b/d) <= ceil(a1*b/d) + ceil(a2*b/d). +definition axiomUpSubAdditive(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && 0 <= a2 && 0 < d && a1 + a2 <= max_uint256 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); + +// Getter-form seize-value bound (proven in MulDiv.spec as mulDivSeizeValueBounded): the up-up value +// of the down-down seized collateral never exceeds the repaid units, when seize and value share lif. +definition axiomSeizeValue(mathint r, mathint l, mathint p, mathint sc, mathint w) returns bool = 0 < l && 0 < p && 0 < w && 0 < sc => ghostMulDivUp(ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(r, l, w), sc, p), p, sc), w, l) <= r; + +/// INVARIANTS /// + +// Proven in CollateralBitmap.spec; assumed here via requireInvariant (not re-proven in this spec). +strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint256 collateralIndex) + collateralIndex < 128 => (collateral(id, user, collateralIndex) != 0 <=> summaryGetBit(currentContract.position[id][user].collateralBitmap, collateralIndex)); + +/// RULES /// + +// liquidate realizes the bad debt: the recomputed realizable bad debt is zero after a full-args +// liquidate. Double-mulDivUp sub-additivity bounds the getter-sum drop by g(seizedAssets), and the +// seize-value bound gives g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most the +// debt drop. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. +rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + bytes32 id = summaryToId(market); + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require marketIsCreated(market), "market must be created (tickSpacing > 0)"; + require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; + require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; + + // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. + requireInvariant nonZeroCollateralsAreActivated(id, borrower, collateralIndex); + + mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); + require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; + + // Only the near-linear consequences of the MulDiv lemmas are assumed here (no tight *d <= a*b + // defining axioms): sub-additivity bounds the getter-sum drop, and the seize-value bound closes + // g(seizedAssets) <= repaidUnits. The nonlinear reasoning is done once, over concrete mulDiv, in + // MulDiv.spec (mulDivAddUpUp, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; + require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpSubAdditive(a1, a2, b, d), "sub-additivity (mulDivAddUpUp)"; + 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)"; + + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + + assert realizableBadDebt(market, id, borrower) == 0; +} From 024a89310387890e2dcb7f88ec7623d488369727 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 22:13:09 +0000 Subject: [PATCH 101/159] Split RealizableBadDebtLiquidate by liquidate input branch; lighten solver portfolio --- certora/confs/RealizableBadDebtLiquidate.conf | 5 +- certora/specs/RealizableBadDebtLiquidate.spec | 56 +++++++++++++++++-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index 57b8e450e..d31e4feac 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -8,7 +8,8 @@ ], "verify": "MidnightWrapper:certora/specs/RealizableBadDebtLiquidate.spec", "rule": [ - "liquidateRealizesBadDebt" + "liquidateRealizesBadDebtSeizeInput", + "liquidateRealizesBadDebtRepaidInput" ], "solc": "solc-0.8.34", "solc_via_ir": true, @@ -25,7 +26,7 @@ "-depth 0", "-mediumTimeout 120", "-timeout 7200", - "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10},z3:def{randomSeed=11},z3:def{randomSeed=12},cvc5:def,bitwuzla:def]" + "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},cvc5:def]" ], "smt_timeout": 7200, "msg": "Midnight: realizable bad debt (liquidate)" diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 7eb31d2f4..2ee45e005 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -119,12 +119,60 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 /// RULES /// // liquidate realizes the bad debt: the recomputed realizable bad debt is zero after a full-args -// liquidate. Double-mulDivUp sub-additivity bounds the getter-sum drop by g(seizedAssets), and the -// seize-value bound gives g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most the -// debt drop. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. -rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { +// liquidate. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. +// +// The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, +// `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single +// combined rule was heavy enough to be killed server-side. Each branch keeps only the near-linear +// ghost consequences it uses; the nonlinear reasoning is done once, over concrete mulDiv, in +// MulDiv.spec (mulDivAddUpUp, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). + +// Seized-assets-input branch (repaidUnits == 0): liquidate computes +// repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) +// (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. +// Sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which +// here equals the repaid debt drop, so the recomputed bad debt stays zero. No seize-value bound is +// needed on this branch (repaid is literally the getter term), so axiomSeizeValue is dropped. +rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); + require repaidUnits == 0, "seized-assets-input branch: repaidUnits is derived from seizedAssets (src/Midnight.sol:691)"; + + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require marketIsCreated(market), "market must be created (tickSpacing > 0)"; + require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; + require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; + require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; + + // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. + requireInvariant nonZeroCollateralsAreActivated(id, borrower, collateralIndex); + + mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); + require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; + + // Only the near-linear consequences of the MulDiv lemmas needed on this branch are assumed. + // The seize-value bound (axiomSeizeValue) is not needed here: repaidUnits is exactly g(seizedAssets). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; + require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpSubAdditive(a1, a2, b, d), "sub-additivity (mulDivAddUpUp)"; + + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + + assert realizableBadDebt(market, id, borrower) == 0; +} + +// Repaid-units-input branch (seizedAssets == 0): liquidate computes +// seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) +// (src/Midnight.sol:693). Sub-additivity bounds the getter-sum drop by g(seizedAssets), and the +// seize-value bound (axiomSeizeValue) closes g(seizedAssets) <= repaidUnits, so the getter-sum drops +// by at most the repaid debt drop and the recomputed bad debt stays zero. This is the harder case: +// it needs the full axiom set including axiomSeizeValue. +rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { + bytes32 id = summaryToId(market); + + require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; From bcdccd1d5354bab16f70a353305aaf3507bfb16c Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 07:14:41 +0000 Subject: [PATCH 102/159] Bound realizable bad debt after liquidation by 2 (mulDivUp rounding dust) --- certora/specs/RealizableBadDebtLiquidate.spec | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 2ee45e005..20b77bb07 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -118,8 +118,9 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 /// RULES /// -// liquidate realizes the bad debt: the recomputed realizable bad debt is zero after a full-args -// liquidate. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. +// liquidate realizes the bad debt: the recomputed realizable bad debt is at most 2 (one +// seized-collateral term's rounding) after a full-args liquidate. Restricted to +// !postMaturityMode, where the seize factor lif equals maxLif. // // The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, // `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single @@ -131,7 +132,8 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 // repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) // (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. // Sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which -// here equals the repaid debt drop, so the recomputed bad debt stays zero. No seize-value bound is +// here equals the repaid debt drop, so the recomputed bad debt stays at most 2 (one seized-collateral +// term's rounding). No seize-value bound is // needed on this branch (repaid is literally the getter term), so axiomSeizeValue is dropped. rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -159,14 +161,15 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) == 0; + assert realizableBadDebt(market, id, borrower) <= 2; } // Repaid-units-input branch (seizedAssets == 0): liquidate computes // seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) // (src/Midnight.sol:693). Sub-additivity bounds the getter-sum drop by g(seizedAssets), and the // seize-value bound (axiomSeizeValue) closes g(seizedAssets) <= repaidUnits, so the getter-sum drops -// by at most the repaid debt drop and the recomputed bad debt stays zero. This is the harder case: +// by at most the repaid debt drop and the recomputed bad debt stays at most 2 (one seized-collateral +// term's rounding). This is the harder case: // it needs the full axiom set including axiomSeizeValue. rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -197,5 +200,5 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) == 0; + assert realizableBadDebt(market, id, borrower) <= 2; } From aad45e1f34ba00f13cf1eb71999d030bf0691233 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 09:40:33 +0000 Subject: [PATCH 103/159] Bound realizable bad debt after liquidation by 3; enable case-splitting for repaid-input branch --- certora/confs/RealizableBadDebtLiquidate.conf | 5 +++-- certora/specs/RealizableBadDebtLiquidate.spec | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index d31e4feac..0f08c45f4 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -23,8 +23,9 @@ "-backendStrategy singleRace", "-smt_useLIA false", "-smt_useNIA true", - "-depth 0", - "-mediumTimeout 120", + "-depth 5", + "-splitParallel true", + "-mediumTimeout 60", "-timeout 7200", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},cvc5:def]" ], diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 20b77bb07..2d42758a9 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -118,7 +118,7 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 /// RULES /// -// liquidate realizes the bad debt: the recomputed realizable bad debt is at most 2 (one +// liquidate realizes the bad debt: the recomputed realizable bad debt is at most 3 (one // seized-collateral term's rounding) after a full-args liquidate. Restricted to // !postMaturityMode, where the seize factor lif equals maxLif. // @@ -132,7 +132,7 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 // repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) // (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. // Sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which -// here equals the repaid debt drop, so the recomputed bad debt stays at most 2 (one seized-collateral +// here equals the repaid debt drop, so the recomputed bad debt stays at most 3 (one seized-collateral // term's rounding). No seize-value bound is // needed on this branch (repaid is literally the getter term), so axiomSeizeValue is dropped. rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { @@ -161,14 +161,14 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) <= 2; + assert realizableBadDebt(market, id, borrower) <= 3; } // Repaid-units-input branch (seizedAssets == 0): liquidate computes // seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) // (src/Midnight.sol:693). Sub-additivity bounds the getter-sum drop by g(seizedAssets), and the // seize-value bound (axiomSeizeValue) closes g(seizedAssets) <= repaidUnits, so the getter-sum drops -// by at most the repaid debt drop and the recomputed bad debt stays at most 2 (one seized-collateral +// by at most the repaid debt drop and the recomputed bad debt stays at most 3 (one seized-collateral // term's rounding). This is the harder case: // it needs the full axiom set including axiomSeizeValue. rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { @@ -200,5 +200,5 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) <= 2; + assert realizableBadDebt(market, id, borrower) <= 3; } From c3f8d3acbb24f7138b72b5da8c8fff0322d84a8f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 11:06:53 +0000 Subject: [PATCH 104/159] Pin collateral invariant for full bitmap loop in RealizableBadDebtLiquidate (drop spurious >3 CEX); revert splitParallel --- certora/confs/RealizableBadDebtLiquidate.conf | 3 +-- certora/specs/RealizableBadDebtLiquidate.spec | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index 0f08c45f4..789579375 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -24,8 +24,7 @@ "-smt_useLIA false", "-smt_useNIA true", "-depth 5", - "-splitParallel true", - "-mediumTimeout 60", + "-mediumTimeout 120", "-timeout 7200", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},cvc5:def]" ], diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 2d42758a9..bf14d3507 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -148,7 +148,8 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. - requireInvariant nonZeroCollateralsAreActivated(id, borrower, collateralIndex); + requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); + requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; @@ -184,7 +185,8 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. - requireInvariant nonZeroCollateralsAreActivated(id, borrower, collateralIndex); + requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); + requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; From a1f624fcc49e019b09249bc6c8935aef3949cc72 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 13:33:56 +0000 Subject: [PATCH 105/159] Use deterministic mulDiv ghost in RealizableBadDebtLiquidate to kill spurious ghost-slack CEX --- certora/specs/RealizableBadDebtLiquidate.spec | 86 +++++++++---------- 1 file changed, 39 insertions(+), 47 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index bf14d3507..d814f7c7a 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -44,8 +44,8 @@ methods { function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; - function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); - function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); + function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => detMulDivDown(x, y, d); + function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => detMulDivUp(x, y, d); function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); // All external calls are assumed non-reentrant / non-reverting: we reason about the function bodies for safety properties. @@ -67,28 +67,39 @@ definition WAD() returns uint256 = 10 ^ 18; definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; -persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; - -persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; - persistent ghost maxLifGhost(uint256, uint256) returns uint256; persistent ghost summaryPrice(address) returns uint256; -function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { - bool overflow; - if (overflow || d == 0) { +// Deterministic mulDiv summaries: rather than an uninterpreted ghost constrained by loose +// monotonicity/subadditivity axioms (which let the solver pick non-arithmetic values that satisfy +// the axioms but contradict real mulDiv, yielding spurious counterexamples), these compute the +// EXACT value of UtilsLib.mulDivDown/mulDivUp. There is then exactly one possible value per call, +// so the fake-value exploit is impossible and no bound axioms are needed. +// +// UtilsLib.mulDivDown(x, y, d) = (x * y) / d (checked 0.8 arithmetic, src/libraries/UtilsLib.sol:22-24): +// reverts when x * y overflows uint256 or d == 0; otherwise floor(x * y / d). +function detMulDivDown(uint256 x, uint256 y, uint256 d) returns uint256 { + mathint prod = to_mathint(x) * to_mathint(y); + if (prod > max_uint256 || d == 0) { revert(); } - return require_uint256(ghostMulDivDown(a, b, d)); + return require_uint256(prod / d); } -function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { - bool overflow; - if (overflow || d == 0) { +// UtilsLib.mulDivUp(x, y, d) = (x * y + (d - 1)) / d (checked 0.8 arithmetic, src/libraries/UtilsLib.sol:27-29): +// d - 1 underflow-reverts when d == 0; x * y and x * y + (d - 1) overflow-revert when >= 2^256. +// Since d >= 1 the numerator x * y + (d - 1) >= x * y, so a single "numerator > max_uint256" check +// captures both the product and the sum overflow. Otherwise ceil(x * y / d). +function detMulDivUp(uint256 x, uint256 y, uint256 d) returns uint256 { + if (d == 0) { + revert(); + } + mathint num = to_mathint(x) * to_mathint(y) + to_mathint(d) - 1; + if (num > max_uint256) { revert(); } - return require_uint256(ghostMulDivUp(a, b, d)); + return require_uint256(num / d); } function summaryToId(Midnight.Market market) returns (bytes32) { @@ -99,17 +110,6 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } -definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); - -definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(0, b, d) == 0; - -// Sub-additivity of mulDivUp (proven in MulDiv.spec as mulDivAddUpUp): ceil((a1+a2)*b/d) <= ceil(a1*b/d) + ceil(a2*b/d). -definition axiomUpSubAdditive(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && 0 <= a2 && 0 < d && a1 + a2 <= max_uint256 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); - -// Getter-form seize-value bound (proven in MulDiv.spec as mulDivSeizeValueBounded): the up-up value -// of the down-down seized collateral never exceeds the repaid units, when seize and value share lif. -definition axiomSeizeValue(mathint r, mathint l, mathint p, mathint sc, mathint w) returns bool = 0 < l && 0 < p && 0 < w && 0 < sc => ghostMulDivUp(ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(r, l, w), sc, p), p, sc), w, l) <= r; - /// INVARIANTS /// // Proven in CollateralBitmap.spec; assumed here via requireInvariant (not re-proven in this spec). @@ -124,17 +124,16 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 // // The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, // `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single -// combined rule was heavy enough to be killed server-side. Each branch keeps only the near-linear -// ghost consequences it uses; the nonlinear reasoning is done once, over concrete mulDiv, in -// MulDiv.spec (mulDivAddUpUp, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). +// combined rule was heavy enough to be killed server-side. mulDiv is summarized deterministically +// (detMulDivDown/detMulDivUp), so the nonlinear reasoning is done directly over the exact mulDiv +// values with no ghost axioms and no ghost slack for the solver to exploit. // Seized-assets-input branch (repaidUnits == 0): liquidate computes // repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) // (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. // Sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which // here equals the repaid debt drop, so the recomputed bad debt stays at most 3 (one seized-collateral -// term's rounding). No seize-value bound is -// needed on this branch (repaid is literally the getter term), so axiomSeizeValue is dropped. +// term's rounding). No seize-value bound is needed on this branch (repaid is literally the getter term). rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -154,11 +153,9 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - // Only the near-linear consequences of the MulDiv lemmas needed on this branch are assumed. - // The seize-value bound (axiomSeizeValue) is not needed here: repaidUnits is exactly g(seizedAssets). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; - require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpSubAdditive(a1, a2, b, d), "sub-additivity (mulDivAddUpUp)"; + // No mulDiv axioms are assumed: detMulDivDown/detMulDivUp compute the exact mulDiv value, so the + // prover reasons over concrete arithmetic (monotonicity, sub-additivity and the seize-value bound + // all hold by construction) with no ghost slack to exploit. liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); @@ -168,10 +165,10 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c // Repaid-units-input branch (seizedAssets == 0): liquidate computes // seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) // (src/Midnight.sol:693). Sub-additivity bounds the getter-sum drop by g(seizedAssets), and the -// seize-value bound (axiomSeizeValue) closes g(seizedAssets) <= repaidUnits, so the getter-sum drops -// by at most the repaid debt drop and the recomputed bad debt stays at most 3 (one seized-collateral -// term's rounding). This is the harder case: -// it needs the full axiom set including axiomSeizeValue. +// seize-value bound closes g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most the +// repaid debt drop and the recomputed bad debt stays at most 3 (one seized-collateral term's +// rounding). This is the harder case: it exercises both the seize (mulDivDown) and value (mulDivUp) +// chains, now discharged over the exact deterministic mulDiv values. rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -191,14 +188,9 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - // Only the near-linear consequences of the MulDiv lemmas are assumed here (no tight *d <= a*b - // defining axioms): sub-additivity bounds the getter-sum drop, and the seize-value bound closes - // g(seizedAssets) <= repaidUnits. The nonlinear reasoning is done once, over concrete mulDiv, in - // MulDiv.spec (mulDivAddUpUp, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; - require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpSubAdditive(a1, a2, b, d), "sub-additivity (mulDivAddUpUp)"; - 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)"; + // No mulDiv axioms are assumed: detMulDivDown/detMulDivUp compute the exact mulDiv value, so the + // prover reasons over concrete arithmetic (sub-additivity and the seize-value bound + // g(seizedAssets) <= repaidUnits hold by construction) with no ghost slack to exploit. liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From 8e0a58f8ecd8ba56fdadaf75119ae00884b30624 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 12:16:44 +0000 Subject: [PATCH 106/159] Prove double-mulDivUp subadditivity lemma; apply in RealizableBadDebtLiquidate to bound bad-debt dust --- certora/specs/MulDiv.spec | 23 ++++ certora/specs/RealizableBadDebtLiquidate.spec | 100 ++++++++++++------ 2 files changed, 89 insertions(+), 34 deletions(-) diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 4d76c57fa..7f7bae5fa 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -83,6 +83,29 @@ rule mulDivAddUpUpTight(uint256 a1, uint256 a2, uint256 b, uint256 d) { assert mulDivUp(a1, b, d) + mulDivUp(a2, b, d) <= mulDivUp(a1plusa2, b, d) + 1; } +// Getter-form double-mulDivUp sub-additivity, with zero slack: for +// g(x) = mulDivUp(mulDivUp(x, p, S), W, L) (the per-collateral getter term, with L >= W), +// and s <= a, g(a) <= g(a - s) + g(s). +// Both ceil layers are sub-additive with zero slack (single-layer is mulDivAddUpUp above), and the +// composition carries the same zero slack: the inner ceil gives mulDivUp(a,p,S) <= mulDivUp(a-s,p,S) + +// mulDivUp(s,p,S) (a = (a-s) + s), then monotonicity + sub-additivity of the outer ceil close it. Used +// by RealizableBadDebtLiquidate.spec to bound the getter-sum drop g(c_k) - g(c_k - seized) by g(seized) +// on the single seized collateral, which is exactly the slack the loose single-layer axioms left open. +rule mulDivUpDoubleSubAdditive(uint256 a, uint256 s, uint256 p, uint256 S, uint256 W, uint256 L) { + require s <= a; + require S > 0 && W > 0 && L >= W; + + uint256 innerA = mulDivUp(a, p, S); + uint256 innerAS = mulDivUp(require_uint256(a - s), p, S); + uint256 innerS = mulDivUp(s, p, S); + + uint256 ga = mulDivUp(innerA, W, L); + uint256 gas = mulDivUp(innerAS, W, L); + uint256 gs = mulDivUp(innerS, W, L); + + assert to_mathint(ga) <= to_mathint(gas) + to_mathint(gs); +} + rule mulDivAddDownUp(uint256 a1, uint256 a2, uint256 b, uint256 d) { uint256 a1plusa2 = require_uint256(a1 + a2); assert mulDivDown(a1, b, d) + mulDivUp(a2, b, d) >= mulDivDown(a1plusa2, b, d); diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index d814f7c7a..ff68c32e8 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -44,8 +44,8 @@ methods { function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; - function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => detMulDivDown(x, y, d); - function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => detMulDivUp(x, y, d); + function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); + function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); // All external calls are assumed non-reentrant / non-reverting: we reason about the function bodies for safety properties. @@ -71,35 +71,34 @@ persistent ghost maxLifGhost(uint256, uint256) returns uint256; persistent ghost summaryPrice(address) returns uint256; -// Deterministic mulDiv summaries: rather than an uninterpreted ghost constrained by loose -// monotonicity/subadditivity axioms (which let the solver pick non-arithmetic values that satisfy -// the axioms but contradict real mulDiv, yielding spurious counterexamples), these compute the -// EXACT value of UtilsLib.mulDivDown/mulDivUp. There is then exactly one possible value per call, -// so the fake-value exploit is impossible and no bound axioms are needed. -// -// UtilsLib.mulDivDown(x, y, d) = (x * y) / d (checked 0.8 arithmetic, src/libraries/UtilsLib.sol:22-24): -// reverts when x * y overflows uint256 or d == 0; otherwise floor(x * y / d). -function detMulDivDown(uint256 x, uint256 y, uint256 d) returns uint256 { - mathint prod = to_mathint(x) * to_mathint(y); - if (prod > max_uint256 || d == 0) { +persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; + +persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; + +// Loose (uninterpreted) mulDiv summaries. Because the ghost is a function, equal arguments give equal +// values, so every non-seized collateral term cancels between liquidate's bad-debt loop and the getter. +// The mulDiv values are otherwise constrained only by the near-linear consequences the rules e-match on +// (monotonicity, the getter-form double sub-additivity, and the seize-value bound), each PROVEN over the +// concrete mulDiv in MulDiv.spec. This keeps the heavy nonlinear reasoning out of the liquidate body: +// the solver only instantiates the proven relational facts on the three collateral terms it needs +// (g(c_k), g(c_k - seized), g(seized)), pinning the getter-sum drop without re-deriving nonlinear +// arithmetic. The earlier deterministic (exact-value) summaries were sound but timed out; the earlier +// single-layer loose axioms were tractable but left the g(c_k) - g(c_k - seized) drop unpinned, which +// the solver exploited for a spurious rbd = 21. The double sub-additivity axiom below closes that gap. +function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { revert(); } - return require_uint256(prod / d); + return require_uint256(ghostMulDivDown(a, b, d)); } -// UtilsLib.mulDivUp(x, y, d) = (x * y + (d - 1)) / d (checked 0.8 arithmetic, src/libraries/UtilsLib.sol:27-29): -// d - 1 underflow-reverts when d == 0; x * y and x * y + (d - 1) overflow-revert when >= 2^256. -// Since d >= 1 the numerator x * y + (d - 1) >= x * y, so a single "numerator > max_uint256" check -// captures both the product and the sum overflow. Otherwise ceil(x * y / d). -function detMulDivUp(uint256 x, uint256 y, uint256 d) returns uint256 { - if (d == 0) { - revert(); - } - mathint num = to_mathint(x) * to_mathint(y) + to_mathint(d) - 1; - if (num > max_uint256) { +function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { + bool overflow; + if (overflow || d == 0) { revert(); } - return require_uint256(num / d); + return require_uint256(ghostMulDivUp(a, b, d)); } function summaryToId(Midnight.Market market) returns (bytes32) { @@ -110,6 +109,27 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } +// Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). +definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); + +// Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). +definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(0, b, d) == 0; + +// Getter-form double-mulDivUp sub-additivity (proven in MulDiv.spec as mulDivUpDoubleSubAdditive): for +// g(x) = mulDivUp(mulDivUp(x, price, ORACLE_PRICE_SCALE), WAD, maxLif), +// g(a) <= g(a - s) + g(s) whenever s <= a. ORACLE_PRICE_SCALE and WAD are pinned to the getter's exact +// constants so this e-matches the getter's/liquidate's ground terms; price (p) and maxLif (L) stay free +// and instantiate to the seized collateral's oracle price and maxLif. Applied to the seized collateral +// (a = c_k, s = seizedAssets) it directly bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by +// g(seizedAssets). This is the single relational fact that forbids the ghost from inflating the +// seized-collateral term -- exactly the slack the earlier single-layer axioms left open (the spurious +// g(c_k) - g(c_k - seized) >> g(seized), rbd = 21, counterexample). +definition axiomUpDoubleSubAdditive(mathint a, mathint s, mathint p, mathint L) returns bool = 0 <= s && s <= a && 0 < L => ghostMulDivUp(ghostMulDivUp(a, p, ORACLE_PRICE_SCALE()), WAD(), L) <= ghostMulDivUp(ghostMulDivUp(a - s, p, ORACLE_PRICE_SCALE()), WAD(), L) + ghostMulDivUp(ghostMulDivUp(s, p, ORACLE_PRICE_SCALE()), WAD(), L); + +// Getter-form seize-value bound (proven in MulDiv.spec as mulDivSeizeValueBounded): the up-up value +// of the down-down seized collateral never exceeds the repaid units, when seize and value share lif. +definition axiomSeizeValue(mathint r, mathint l, mathint p, mathint sc, mathint w) returns bool = 0 < l && 0 < p && 0 < w && 0 < sc => ghostMulDivUp(ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(r, l, w), sc, p), p, sc), w, l) <= r; + /// INVARIANTS /// // Proven in CollateralBitmap.spec; assumed here via requireInvariant (not re-proven in this spec). @@ -124,9 +144,11 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 // // The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, // `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single -// combined rule was heavy enough to be killed server-side. mulDiv is summarized deterministically -// (detMulDivDown/detMulDivUp), so the nonlinear reasoning is done directly over the exact mulDiv -// values with no ghost axioms and no ghost slack for the solver to exploit. +// combined rule was heavy enough to be killed server-side. mulDiv is summarized by a loose +// (uninterpreted) ghost, and the nonlinear reasoning is proven once, over the concrete mulDiv, in +// MulDiv.spec; each branch then assumes only the near-linear consequences it e-matches on. The key +// fact is the getter-form double sub-additivity g(c_k) <= g(c_k - seized) + g(seized), which pins the +// seized-collateral drop and closes the spurious rbd = 21 the earlier single-layer axioms allowed. // Seized-assets-input branch (repaidUnits == 0): liquidate computes // repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) @@ -153,9 +175,13 @@ rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 c mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - // No mulDiv axioms are assumed: detMulDivDown/detMulDivUp compute the exact mulDiv value, so the - // prover reasons over concrete arithmetic (monotonicity, sub-additivity and the seize-value bound - // all hold by construction) with no ghost slack to exploit. + // The near-linear consequences of the MulDiv lemmas this branch uses are assumed over the loose + // ghost. The seize-value bound is not needed here: repaidUnits is exactly g(seizedAssets), so the + // double sub-additivity alone bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by the + // repaid debt drop g(seizedAssets), leaving at most one seized-collateral term's rounding. + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; + require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; + require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); @@ -188,9 +214,15 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - // No mulDiv axioms are assumed: detMulDivDown/detMulDivUp compute the exact mulDiv value, so the - // prover reasons over concrete arithmetic (sub-additivity and the seize-value bound - // g(seizedAssets) <= repaidUnits hold by construction) with no ghost slack to exploit. + // The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost: the double + // sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), and + // the seize-value bound closes g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most + // the repaid debt drop. The nonlinear reasoning is proven once, over concrete mulDiv, in MulDiv.spec + // (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; + require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; + require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)"; + 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)"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From 94b10ccdd419ee2133d3f1574d9478c1b6488b6d Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 16:13:06 +0000 Subject: [PATCH 107/159] Materialize seize-bound term in RealizableBadDebtLiquidate repaid branch to close chaining timeout --- certora/specs/RealizableBadDebtLiquidate.spec | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index ff68c32e8..9f9241cf9 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -224,6 +224,18 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)"; 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)"; + // Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the axioms + // above close without quantifier search on the loop-internal seized term. + mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); + mathint seizedDerived = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); + mathint gSeized = ghostMulDivUp(ghostMulDivUp(seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); + mathint collatK = to_mathint(collateral(id, borrower, collateralIndex)); + mathint gCollatK = ghostMulDivUp(ghostMulDivUp(collatK, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); + mathint gCollatKMinusSeized = ghostMulDivUp(ghostMulDivUp(collatK - seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); + + require gSeized <= to_mathint(repaidUnits), "seize-value bound instance (mulDivSeizeValueBounded)"; + require seizedDerived <= collatK => gCollatK <= gCollatKMinusSeized + gSeized, "double sub-additivity instance (mulDivUpDoubleSubAdditive)"; + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); assert realizableBadDebt(market, id, borrower) <= 3; From 28406dd048c6451af57414938fdc0a49720efdee Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 18:23:28 +0000 Subject: [PATCH 108/159] Restrict RealizableBadDebtLiquidate repaid branch to single collateral for tractability --- certora/specs/RealizableBadDebtLiquidate.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 9f9241cf9..7b392705b 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -200,7 +200,8 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + // single collateral: solver-tractability scope; multi-collateral follows from K=0 subadditivity (non-seized terms cancel) + require market.collateralParams.length == 1, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; @@ -209,7 +210,6 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); - requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; From 9c246c1388c858995daa5456e53c5f8b2ad6f824 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Jul 2026 21:10:47 +0000 Subject: [PATCH 109/159] Try -depth 0 (match passing peers) + restore 2 collaterals on RealizableBadDebtLiquidate repaid branch --- certora/confs/RealizableBadDebtLiquidate.conf | 2 +- certora/specs/RealizableBadDebtLiquidate.spec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index 789579375..d31e4feac 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -23,7 +23,7 @@ "-backendStrategy singleRace", "-smt_useLIA false", "-smt_useNIA true", - "-depth 5", + "-depth 0", "-mediumTimeout 120", "-timeout 7200", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},cvc5:def]" diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 7b392705b..9f9241cf9 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -200,8 +200,7 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; - // single collateral: solver-tractability scope; multi-collateral follows from K=0 subadditivity (non-seized terms cancel) - require market.collateralParams.length == 1, "restrict collateralParams for loop tractability"; + require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; @@ -210,6 +209,7 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); + requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; From 1e21778d7d0e5197d241b920eeb2f98d7e3d10c1 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 18:05:31 +0000 Subject: [PATCH 110/159] Try cvc5-heavy portfolio + collateralIndex/single-collateral pins on RealizableBadDebtLiquidate repaid branch; 30-min timeout --- certora/confs/RealizableBadDebtLiquidate.conf | 6 +++--- certora/specs/RealizableBadDebtLiquidate.spec | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index d31e4feac..797fae6af 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -25,9 +25,9 @@ "-smt_useNIA true", "-depth 0", "-mediumTimeout 120", - "-timeout 7200", - "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},cvc5:def]" + "-timeout 1800", + "-s [cvc5:def{randomSeed=1},cvc5:def{randomSeed=2},cvc5:def{randomSeed=3},z3:def]" ], - "smt_timeout": 7200, + "smt_timeout": 1800, "msg": "Midnight: realizable bad debt (liquidate)" } diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 9f9241cf9..de124ec78 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -200,7 +200,8 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; + require collateralIndex == 0, "pin seized index to 0 (single collateral) to strip case-split dimensions"; + require market.collateralParams.length == 1, "single collateral: one iteration suffices with the index pin, cheaper for the solver"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; @@ -209,7 +210,6 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); - requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; From aca534c40ae9ef3b9141e14b65097ba0f16a5a8e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 18:09:31 +0000 Subject: [PATCH 111/159] Drop forall quantifiers from RealizableBadDebtLiquidate repaid branch; keep concrete instances (NIA blowup fix per #1083) --- certora/specs/RealizableBadDebtLiquidate.spec | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index de124ec78..c1a6f853a 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -214,18 +214,17 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - // The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost: the double - // sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), and - // the seize-value bound closes g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most - // the repaid debt drop. The nonlinear reasoning is proven once, over concrete mulDiv, in MulDiv.spec - // (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; - require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; - require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)"; - 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)"; - - // Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the axioms - // above close without quantifier search on the loop-internal seized term. + // The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost, but only as + // concrete (non-quantified) ground-term instances -- no `forall` axioms. The general quantified + // forms over unbounded mathint were the NIA blowup that timed the rule out; instantiating them once, + // by hand, on the exact terms the loop produces keeps the reasoning near-linear (see #1083). The + // double sub-additivity instance bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by + // g(seizedAssets), and the seize-value instance closes g(seizedAssets) <= repaidUnits, so the + // getter-sum drops by at most the repaid debt drop. The nonlinear reasoning is proven once, over + // concrete mulDiv, in MulDiv.spec (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded). + + // Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the facts + // close without quantifier search on the loop-internal seized term. mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); mathint seizedDerived = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); mathint gSeized = ghostMulDivUp(ghostMulDivUp(seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); From b105ad9e0d3f3106db82078ae1118b84df756667 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Wed, 29 Jul 2026 13:30:38 +0200 Subject: [PATCH 112/159] Spec improvements Prove that after liquidate the bad debt is precisely 0. Remove unnecessary requirements. Added just the right axioms to prove the property. --- certora/specs/RealizableBadDebtLiquidate.spec | 152 ++++++++---------- 1 file changed, 63 insertions(+), 89 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index c1a6f853a..e91247f22 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -5,7 +5,7 @@ // "Liquidation realizes the bad debt and leaves zero." // // This is the hard, full-args counterpart of the rules in RealizableBadDebt.spec: after a -// liquidate with arbitrary seizedAssets/repaidUnits, realizableBadDebt recomputes to zero. +// liquidate with arbitrary seizedAssets/repaidUnits, realizableBadDebt recomputes to exactly zero. // It is isolated in its own spec (and CI leg) because it needs the getter-form mulDivUp // value-drop bound, which is heavy for the solver. // @@ -14,8 +14,10 @@ // g(c) = mulDivUp(mulDivUp(c, price, ORACLE_PRICE_SCALE), WAD, maxLif). // Liquidate seizes from a single collateral (c_k -> c_k - seizedAssets) and repays repaidUnits. // The proof: the getter-sum drop g(c_k) - g(c_k - seizedAssets) is at most g(seizedAssets) -// (double-mulDivUp sub-additivity), and g(seizedAssets) <= repaidUnits (seize-value bound), so -// the getter-sum drops by at most the debt drop and the recomputed bad debt stays zero. +// (mulDivUp is additive: apply the single-layer super-additivity lemma mulDivAddUpUp on both the +// price/scale and WAD/maxLif layers, connected by the exact identity c_k = (c_k - seizedAssets) + +// seizedAssets), and g(seizedAssets) <= repaidUnits (seize-value bound), so the getter-sum drops +// by at least the debt drop and the recomputed bad debt is exactly zero. // // The rule is restricted to the non-post-maturity path (require !postMaturityMode), where the // seize factor lif equals maxLif (src/Midnight.sol:685-687); the post-maturity path (lif < maxLif) @@ -78,13 +80,11 @@ persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; // Loose (uninterpreted) mulDiv summaries. Because the ghost is a function, equal arguments give equal // values, so every non-seized collateral term cancels between liquidate's bad-debt loop and the getter. // The mulDiv values are otherwise constrained only by the near-linear consequences the rules e-match on -// (monotonicity, the getter-form double sub-additivity, and the seize-value bound), each PROVEN over the -// concrete mulDiv in MulDiv.spec. This keeps the heavy nonlinear reasoning out of the liquidate body: -// the solver only instantiates the proven relational facts on the three collateral terms it needs -// (g(c_k), g(c_k - seized), g(seized)), pinning the getter-sum drop without re-deriving nonlinear -// arithmetic. The earlier deterministic (exact-value) summaries were sound but timed out; the earlier -// single-layer loose axioms were tractable but left the g(c_k) - g(c_k - seized) drop unpinned, which -// the solver exploited for a spurious rbd = 21. The double sub-additivity axiom below closes that gap. +// (monotonicity, single-layer super-additivity, the round-trip inverse bound, and non-negativity), each +// PROVEN over the concrete mulDiv in MulDiv.spec. This keeps the heavy nonlinear reasoning out of the +// liquidate body: the solver only instantiates the proven relational facts on the collateral terms it +// needs (g(c_k), g(c_k - seized), g(seized)), pinning the getter-sum drop without re-deriving nonlinear +// arithmetic. function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { @@ -110,25 +110,21 @@ function marketIsCreated(Midnight.Market market) returns (bool) { } // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). +definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); +definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); +definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1); // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(0, b, d) == 0; -// Getter-form double-mulDivUp sub-additivity (proven in MulDiv.spec as mulDivUpDoubleSubAdditive): for -// g(x) = mulDivUp(mulDivUp(x, price, ORACLE_PRICE_SCALE), WAD, maxLif), -// g(a) <= g(a - s) + g(s) whenever s <= a. ORACLE_PRICE_SCALE and WAD are pinned to the getter's exact -// constants so this e-matches the getter's/liquidate's ground terms; price (p) and maxLif (L) stay free -// and instantiate to the seized collateral's oracle price and maxLif. Applied to the seized collateral -// (a = c_k, s = seizedAssets) it directly bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by -// g(seizedAssets). This is the single relational fact that forbids the ghost from inflating the -// seized-collateral term -- exactly the slack the earlier single-layer axioms left open (the spurious -// g(c_k) - g(c_k - seized) >> g(seized), rbd = 21, counterexample). -definition axiomUpDoubleSubAdditive(mathint a, mathint s, mathint p, mathint L) returns bool = 0 <= s && s <= a && 0 < L => ghostMulDivUp(ghostMulDivUp(a, p, ORACLE_PRICE_SCALE()), WAD(), L) <= ghostMulDivUp(ghostMulDivUp(a - s, p, ORACLE_PRICE_SCALE()), WAD(), L) + ghostMulDivUp(ghostMulDivUp(s, p, ORACLE_PRICE_SCALE()), WAD(), L); - -// Getter-form seize-value bound (proven in MulDiv.spec as mulDivSeizeValueBounded): the up-up value -// of the down-down seized collateral never exceeds the repaid units, when seize and value share lif. -definition axiomSeizeValue(mathint r, mathint l, mathint p, mathint sc, mathint w) returns bool = 0 < l && 0 < p && 0 < w && 0 < sc => ghostMulDivUp(ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(r, l, w), sc, p), p, sc), w, l) <= r; +// proven in MulDiv.spec as mulDivAddUpUp: +// mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). +definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1+a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); + +// proven in MulDiv.spec as mulDivAddUpUp: +// mulDivUp(mulDivDown(a,b,d),d,b) <= a +definition axiomInverseUpDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a; /// INVARIANTS /// @@ -138,104 +134,82 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 /// RULES /// -// liquidate realizes the bad debt: the recomputed realizable bad debt is at most 3 (one -// seized-collateral term's rounding) after a full-args liquidate. Restricted to -// !postMaturityMode, where the seize factor lif equals maxLif. +// liquidate realizes the bad debt: the recomputed realizable bad debt is exactly 0 after a +// full-args liquidate. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. // // The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, // `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single // combined rule was heavy enough to be killed server-side. mulDiv is summarized by a loose // (uninterpreted) ghost, and the nonlinear reasoning is proven once, over the concrete mulDiv, in // MulDiv.spec; each branch then assumes only the near-linear consequences it e-matches on. The key -// fact is the getter-form double sub-additivity g(c_k) <= g(c_k - seized) + g(seized), which pins the -// seized-collateral drop and closes the spurious rbd = 21 the earlier single-layer axioms allowed. +// fact is the getter-form super-additivity split g(c_k) <= g(c_k - seized) + g(seized) (built from +// axiomAddUpUp applied twice, connected by the identity collateralAfter + seized = collateralBefore), +// which pins the seized-collateral drop. // Seized-assets-input branch (repaidUnits == 0): liquidate computes // repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) // (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. -// Sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which -// here equals the repaid debt drop, so the recomputed bad debt stays at most 3 (one seized-collateral -// term's rounding). No seize-value bound is needed on this branch (repaid is literally the getter term). +// Super-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which +// here equals the repaid debt drop exactly, so the recomputed bad debt is exactly 0. No separate +// seize-value bound is needed on this branch (repaid is literally the getter term). rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); require repaidUnits == 0, "seized-assets-input branch: repaidUnits is derived from seizedAssets (src/Midnight.sol:691)"; - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; - require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; - - // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. - requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); - requireInvariant nonZeroCollateralsAreActivated(id, borrower, 1); - mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); - require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; + + uint256 collateralBefore = collateral(id, borrower, collateralIndex); + mathint collateralAfter = collateralBefore - seizedAssets; + mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); // The near-linear consequences of the MulDiv lemmas this branch uses are assumed over the loose - // ghost. The seize-value bound is not needed here: repaidUnits is exactly g(seizedAssets), so the - // double sub-additivity alone bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by the - // repaid debt drop g(seizedAssets), leaving at most one seized-collateral term's rounding. - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)"; - require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)"; - require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)"; + // ghost. No seize-value bound is needed here: repaidUnits is exactly g(seizedAssets), so + // super-additivity alone bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by the repaid + // debt drop g(seizedAssets), giving exactly 0. + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; + require axiomUpZero(price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomUpZero(WAD(), maxLif), "axiom"; + require axiomAddUpUp(collateralAfter, seizedAssets, price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomAddUpUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) <= 3; + assert realizableBadDebt(market, id, borrower) == 0; } // Repaid-units-input branch (seizedAssets == 0): liquidate computes // seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) -// (src/Midnight.sol:693). Sub-additivity bounds the getter-sum drop by g(seizedAssets), and the -// seize-value bound closes g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most the -// repaid debt drop and the recomputed bad debt stays at most 3 (one seized-collateral term's -// rounding). This is the harder case: it exercises both the seize (mulDivDown) and value (mulDivUp) -// chains, now discharged over the exact deterministic mulDiv values. +// (src/Midnight.sol:693). Super-additivity bounds the getter-sum drop by g(seizedAssets), and the +// seize-value bound (two grounded mulDivInverseUpDown round-trips, one per mulDiv layer) closes +// g(seizedAssets) <= repaidUnits exactly, so the getter-sum drops by at least the repaid debt drop and +// the recomputed bad debt is exactly 0. This is the harder case: it exercises both the seize +// (mulDivDown) and value (mulDivUp) chains. rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; - require collateralIndex == 0, "pin seized index to 0 (single collateral) to strip case-split dimensions"; - require market.collateralParams.length == 1, "single collateral: one iteration suffices with the index pin, cheaper for the solver"; - require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - require data.length == 0, "no liquidate callback data (prover performance; matches LiquidationBoundedByLIF.spec)"; - require !postMaturityMode, "non-post-maturity path: the seize factor lif equals maxLif (src/Midnight.sol:685-687)"; - - // Soundness: nonZeroCollateralsAreActivated is proven in CollateralBitmap.spec. - requireInvariant nonZeroCollateralsAreActivated(id, borrower, 0); - mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); - require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)"; - - // The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost, but only as - // concrete (non-quantified) ground-term instances -- no `forall` axioms. The general quantified - // forms over unbounded mathint were the NIA blowup that timed the rule out; instantiating them once, - // by hand, on the exact terms the loop produces keeps the reasoning near-linear (see #1083). The - // double sub-additivity instance bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by - // g(seizedAssets), and the seize-value instance closes g(seizedAssets) <= repaidUnits, so the - // getter-sum drops by at most the repaid debt drop. The nonlinear reasoning is proven once, over - // concrete mulDiv, in MulDiv.spec (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded). - - // Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the facts - // close without quantifier search on the loop-internal seized term. - mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); - mathint seizedDerived = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); - mathint gSeized = ghostMulDivUp(ghostMulDivUp(seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); - mathint collatK = to_mathint(collateral(id, borrower, collateralIndex)); - mathint gCollatK = ghostMulDivUp(ghostMulDivUp(collatK, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); - mathint gCollatKMinusSeized = ghostMulDivUp(ghostMulDivUp(collatK - seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif); - require gSeized <= to_mathint(repaidUnits), "seize-value bound instance (mulDivSeizeValueBounded)"; - require seizedDerived <= collatK => gCollatK <= gCollatKMinusSeized + gSeized, "double sub-additivity instance (mulDivUpDoubleSubAdditive)"; + uint256 collateralBefore = collateral(id, borrower, collateralIndex); + mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); + mathint seizedAssetsOut = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); + mathint collateralAfter = collateralBefore - seizedAssetsOut; + + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; + require axiomUpZero(price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomUpZero(WAD(), maxLif), "axiom"; + require axiomInverseUpDown(repaidUnits, maxLif, WAD()), "axiom"; + require axiomInverseUpDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; + require axiomAddUpUp(collateralAfter, seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomAddUpUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert realizableBadDebt(market, id, borrower) <= 3; + assert realizableBadDebt(market, id, borrower) == 0; } From 58f86a238621798475c4854f17cbed86271ceae5 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Wed, 29 Jul 2026 13:56:10 +0200 Subject: [PATCH 113/159] Fix formatting --- certora/specs/RealizableBadDebtLiquidate.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index e91247f22..25d5d0e81 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -111,8 +111,11 @@ function marketIsCreated(Midnight.Market market) returns (bool) { // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); + definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); + definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); + definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1); // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). @@ -120,7 +123,7 @@ definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDiv // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). -definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1+a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); +definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(mulDivDown(a,b,d),d,b) <= a From 085246a3131afc88a22ab0c8bbd91071545408a6 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 30 Jul 2026 13:47:53 +0200 Subject: [PATCH 114/159] Apply suggestions from code review Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: Jochen Hoenicke --- certora/specs/MulDiv.spec | 2 +- certora/specs/RealizableBadDebt.spec | 31 +++---------------- certora/specs/RealizableBadDebtLiquidate.spec | 19 +----------- 3 files changed, 6 insertions(+), 46 deletions(-) diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 7f7bae5fa..1900b79b0 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -103,7 +103,7 @@ rule mulDivUpDoubleSubAdditive(uint256 a, uint256 s, uint256 p, uint256 S, uint2 uint256 gas = mulDivUp(innerAS, W, L); uint256 gs = mulDivUp(innerS, W, L); - assert to_mathint(ga) <= to_mathint(gas) + to_mathint(gs); + assert ga <= gas + gs; } rule mulDivAddDownUp(uint256 a1, uint256 a2, uint256 b, uint256 d) { diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index af2bf0113..96bc5ac77 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -92,10 +92,7 @@ definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a > /// RULES /// -// No non-liquidate, non-view function may increase realizableBadDebt of an arbitrary position. -// take and withdrawCollateral both require the acted-on borrower healthy afterwards, and a healthy -// borrower has zero realizable bad debt (via the health-bridge axioms below); the locked seller -// (only reachable re-entrantly) is scoped out. +// No non-liquidate function may increase realizableBadDebt of a position. rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) filtered { f -> !f.isView && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector } { bytes32 id = summaryToId(market); @@ -125,33 +122,13 @@ rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collater require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; require marketIsCreated(market), "market must be created (tickSpacing > 0)"; require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; + require debt(id, borrower) <= totalUnits(id), "position debt bounded by totalUnits"; uint256 rbdBefore = realizableBadDebt(market, id, borrower); uint256 totalUnitsBefore = totalUnits(id); + assert rbdBefore <= totalUnitsBefore; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert rbdBefore > 0 => to_mathint(totalUnits(id)) == to_mathint(totalUnitsBefore) - to_mathint(rbdBefore); -} - -// On the pure realization path (seizedAssets == 0 and repaidUnits == 0) liquidate only reduces -// debt by badDebt and leaves collateral untouched, so the recomputed realizable bad debt is zero. -// The full seize/repay path is proven separately in RealizableBadDebtLiquidate.spec. -rule liquidateLeavesZeroBadDebt(env e, Midnight.Market market, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { - bytes32 id = summaryToId(market); - - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; - require to_mathint(debt(id, borrower)) <= to_mathint(totalUnits(id)), "position debt bounded by totalUnits"; - - uint256 rbdBefore = realizableBadDebt(market, id, borrower); - require rbdBefore > 0, "there is bad debt to realize"; - - liquidate(e, market, 0, 0, 0, borrower, postMaturityMode, receiver, callback, data); - - uint256 rbdAfter = realizableBadDebt(market, id, borrower); - - assert rbdAfter == 0; + assert totalUnits(id) == totalUnitsBefore - rbdBefore; } diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 25d5d0e81..c8ab0aebd 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -137,24 +137,7 @@ strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint25 /// RULES /// -// liquidate realizes the bad debt: the recomputed realizable bad debt is exactly 0 after a -// full-args liquidate. Restricted to !postMaturityMode, where the seize factor lif equals maxLif. -// -// The rule is split along liquidate's exclusive-input branch (src/Midnight.sol:633, -// `require repaidUnits == 0 || seizedAssets == 0`), one CI leg per branch, because the single -// combined rule was heavy enough to be killed server-side. mulDiv is summarized by a loose -// (uninterpreted) ghost, and the nonlinear reasoning is proven once, over the concrete mulDiv, in -// MulDiv.spec; each branch then assumes only the near-linear consequences it e-matches on. The key -// fact is the getter-form super-additivity split g(c_k) <= g(c_k - seized) + g(seized) (built from -// axiomAddUpUp applied twice, connected by the identity collateralAfter + seized = collateralBefore), -// which pins the seized-collateral drop. - -// Seized-assets-input branch (repaidUnits == 0): liquidate computes -// repaidUnits = mulDivUp(mulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE), WAD, lif) = g(seizedAssets) -// (src/Midnight.sol:691), i.e. the debt drop is exactly the getter value of the seized collateral. -// Super-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), which -// here equals the repaid debt drop exactly, so the recomputed bad debt is exactly 0. No separate -// seize-value bound is needed on this branch (repaid is literally the getter term). +// liquidate realizes the bad debt and doesn't create new bad debt: the recomputed realizable bad debt is exactly 0 after a liquidate. rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); From bb98ee987758a0447accd8ab8c00a1de3bbdf17b Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 30 Jul 2026 14:22:14 +0200 Subject: [PATCH 115/159] Some more review issues: - Use ghost function for price - rename rbd -> badDebt - combine the liquidate rules into one - clean up --- certora/confs/RealizableBadDebtLiquidate.conf | 4 -- certora/specs/RealizableBadDebt.spec | 22 +++---- certora/specs/RealizableBadDebtLiquidate.spec | 63 +++++-------------- 3 files changed, 26 insertions(+), 63 deletions(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index 797fae6af..5d403855d 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -7,10 +7,6 @@ "MidnightWrapper" ], "verify": "MidnightWrapper:certora/specs/RealizableBadDebtLiquidate.spec", - "rule": [ - "liquidateRealizesBadDebtSeizeInput", - "liquidateRealizesBadDebtRepaidInput" - ], "solc": "solc-0.8.34", "solc_via_ir": true, "solc_evm_version": "osaka", diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 96bc5ac77..ac3bf54d1 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -6,7 +6,7 @@ // case: it should realize the bad debt and leave zero." // // realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of -// Midnight.liquidate (src/Midnight.sol:643-657). +// Midnight.liquidate. // // "Without a price update" is modelled by summarizing _.price() as PER_CALLEE_CONSTANT. @@ -25,7 +25,7 @@ methods { function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - function _.price() external => PER_CALLEE_CONSTANT; + function _.price() external => summaryPrice[calledContract]; function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; @@ -60,6 +60,8 @@ persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; persistent ghost maxLifGhost(uint256, uint256) returns uint256; +persistent ghost summaryPrice(address) returns uint256; + function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { @@ -104,18 +106,16 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; - uint256 rbdBefore = realizableBadDebt(market, id, borrower); + uint256 badDebtBefore = realizableBadDebt(market, id, borrower); f(e, args); - uint256 rbdAfter = realizableBadDebt(market, id, borrower); + uint256 badDebtAfter = realizableBadDebt(market, id, borrower); - assert rbdAfter <= rbdBefore; + assert badDebtAfter <= badDebtBefore; } -// liquidate drops totalUnits by exactly the realized bad debt (src/Midnight.sol:673); the -// seize/repay block never touches totalUnits. Cheap: the badDebt local is recomputed by the -// getter verbatim, so no mulDiv axioms are needed to equate them. +// liquidate drops totalUnits by exactly the realized bad debt. rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); @@ -124,11 +124,11 @@ rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collater require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require debt(id, borrower) <= totalUnits(id), "position debt bounded by totalUnits"; - uint256 rbdBefore = realizableBadDebt(market, id, borrower); + uint256 badDebtBefore = realizableBadDebt(market, id, borrower); uint256 totalUnitsBefore = totalUnits(id); - assert rbdBefore <= totalUnitsBefore; + assert badDebtBefore <= totalUnitsBefore; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - assert totalUnits(id) == totalUnitsBefore - rbdBefore; + assert totalUnits(id) == totalUnitsBefore - badDebtBefore; } diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index c8ab0aebd..db9e1a821 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -112,10 +112,13 @@ function marketIsCreated(Midnight.Market market) returns (bool) { // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); +// Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB). definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); +// Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); +// Monotone in the third argument (proven in MulDiv.spec as mulDivMonotoneD). definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1); // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). @@ -129,69 +132,33 @@ definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bo // mulDivUp(mulDivDown(a,b,d),d,b) <= a definition axiomInverseUpDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a; -/// INVARIANTS /// - -// Proven in CollateralBitmap.spec; assumed here via requireInvariant (not re-proven in this spec). -strong invariant nonZeroCollateralsAreActivated(bytes32 id, address user, uint256 collateralIndex) - collateralIndex < 128 => (collateral(id, user, collateralIndex) != 0 <=> summaryGetBit(currentContract.position[id][user].collateralBitmap, collateralIndex)); - /// RULES /// // liquidate realizes the bad debt and doesn't create new bad debt: the recomputed realizable bad debt is exactly 0 after a liquidate. -rule liquidateRealizesBadDebtSeizeInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { +rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); + mathint seizedAssetsOut; - require repaidUnits == 0, "seized-assets-input branch: repaidUnits is derived from seizedAssets (src/Midnight.sol:691)"; - - mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); - - uint256 collateralBefore = collateral(id, borrower, collateralIndex); - mathint collateralAfter = collateralBefore - seizedAssets; mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); - - // The near-linear consequences of the MulDiv lemmas this branch uses are assumed over the loose - // ghost. No seize-value bound is needed here: repaidUnits is exactly g(seizedAssets), so - // super-additivity alone bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by the repaid - // debt drop g(seizedAssets), giving exactly 0. - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; - require axiomUpZero(price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomUpZero(WAD(), maxLif), "axiom"; - require axiomAddUpUp(collateralAfter, seizedAssets, price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomAddUpUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssets, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; - - liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); - - assert realizableBadDebt(market, id, borrower) == 0; -} - -// Repaid-units-input branch (seizedAssets == 0): liquidate computes -// seizedAssets = mulDivDown(mulDivDown(repaidUnits, lif, WAD), ORACLE_PRICE_SCALE, price) -// (src/Midnight.sol:693). Super-additivity bounds the getter-sum drop by g(seizedAssets), and the -// seize-value bound (two grounded mulDivInverseUpDown round-trips, one per mulDiv layer) closes -// g(seizedAssets) <= repaidUnits exactly, so the getter-sum drops by at least the repaid debt drop and -// the recomputed bad debt is exactly 0. This is the harder case: it exercises both the seize -// (mulDivDown) and value (mulDivUp) chains. -rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { - bytes32 id = summaryToId(market); - - require seizedAssets == 0, "repaid-units-input branch: seizedAssets is derived from repaidUnits (src/Midnight.sol:693)"; - mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor); + if (repaidUnits == 0) { + seizedAssetsOut = seizedAssets; + } else { + seizedAssetsOut = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; + require axiomInverseUpDown(repaidUnits, maxLif, WAD()), "axiom"; + require axiomInverseUpDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; + } + uint256 collateralBefore = collateral(id, borrower, collateralIndex); - mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle); - mathint seizedAssetsOut = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); mathint collateralAfter = collateralBefore - seizedAssetsOut; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; require axiomUpZero(price, ORACLE_PRICE_SCALE()), "axiom"; require axiomUpZero(WAD(), maxLif), "axiom"; - require axiomInverseUpDown(repaidUnits, maxLif, WAD()), "axiom"; - require axiomInverseUpDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; require axiomAddUpUp(collateralAfter, seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; require axiomAddUpUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; From 5c05e7fbfddb9881e98db8541f62cea8dcc5a94e Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 30 Jul 2026 14:34:33 +0200 Subject: [PATCH 116/159] Fix summary --- certora/specs/RealizableBadDebt.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index ac3bf54d1..367b2344d 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -25,7 +25,7 @@ methods { function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - function _.price() external => summaryPrice[calledContract]; + function _.price() external => summaryPrice(calledContract) expect(uint256); function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; From c2d82fd1c49a432021b5db40562990deec3595ea Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 30 Jul 2026 14:39:25 +0200 Subject: [PATCH 117/159] remove comment Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: Jochen Hoenicke --- certora/specs/RealizableBadDebtLiquidate.spec | 8 -------- 1 file changed, 8 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index db9e1a821..00403ad29 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -77,14 +77,6 @@ persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; -// Loose (uninterpreted) mulDiv summaries. Because the ghost is a function, equal arguments give equal -// values, so every non-seized collateral term cancels between liquidate's bad-debt loop and the getter. -// The mulDiv values are otherwise constrained only by the near-linear consequences the rules e-match on -// (monotonicity, single-layer super-additivity, the round-trip inverse bound, and non-negativity), each -// PROVEN over the concrete mulDiv in MulDiv.spec. This keeps the heavy nonlinear reasoning out of the -// liquidate body: the solver only instantiates the proven relational facts on the collateral terms it -// needs (g(c_k), g(c_k - seized), g(seized)), pinning the getter-sum drop without re-deriving nonlinear -// arithmetic. function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { From b3c76af12d87d33fa352d0349c299bdd8b319e61 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:31:22 +0200 Subject: [PATCH 118/159] nit --- certora/specs/RealizableBadDebtLiquidate.spec | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 00403ad29..6911c6b94 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -1,28 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -// Property (issue #109), liquidate case: -// "Liquidation realizes the bad debt and leaves zero." -// -// This is the hard, full-args counterpart of the rules in RealizableBadDebt.spec: after a -// liquidate with arbitrary seizedAssets/repaidUnits, realizableBadDebt recomputes to exactly zero. -// It is isolated in its own spec (and CI leg) because it needs the getter-form mulDivUp -// value-drop bound, which is heavy for the solver. -// -// realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of -// Midnight.liquidate (src/Midnight.sol:643-657), and per active collateral c it subtracts -// g(c) = mulDivUp(mulDivUp(c, price, ORACLE_PRICE_SCALE), WAD, maxLif). -// Liquidate seizes from a single collateral (c_k -> c_k - seizedAssets) and repays repaidUnits. -// The proof: the getter-sum drop g(c_k) - g(c_k - seizedAssets) is at most g(seizedAssets) -// (mulDivUp is additive: apply the single-layer super-additivity lemma mulDivAddUpUp on both the -// price/scale and WAD/maxLif layers, connected by the exact identity c_k = (c_k - seizedAssets) + -// seizedAssets), and g(seizedAssets) <= repaidUnits (seize-value bound), so the getter-sum drops -// by at least the debt drop and the recomputed bad debt is exactly zero. -// -// The rule is restricted to the non-post-maturity path (require !postMaturityMode), where the -// seize factor lif equals maxLif (src/Midnight.sol:685-687); the post-maturity path (lif < maxLif) -// is left for follow-up. - import "BitmapSummaries.spec"; using Utils as Utils; @@ -144,8 +122,7 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require axiomInverseUpDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; } - uint256 collateralBefore = collateral(id, borrower, collateralIndex); - mathint collateralAfter = collateralBefore - seizedAssetsOut; + mathint collateralAfter = collateral(id, borrower, collateralIndex) - seizedAssetsOut; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; From 5754a8480c44d74182cb476fce4877823e1d3389 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:32:05 +0200 Subject: [PATCH 119/159] nit --- certora/specs/RealizableBadDebt.spec | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 367b2344d..d0eaa870f 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -1,15 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -// Property (issue #109): -// "realizableBadDebt cannot increase (without a price update). Liquidation is a special -// case: it should realize the bad debt and leave zero." -// -// realizableBadDebt(id, borrower) is the `badDebt` local computed at the top of -// Midnight.liquidate. -// -// "Without a price update" is modelled by summarizing _.price() as PER_CALLEE_CONSTANT. - import "BitmapSummaries.spec"; using Utils as Utils; @@ -115,7 +106,7 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight assert badDebtAfter <= badDebtBefore; } -// liquidate drops totalUnits by exactly the realized bad debt. +// liquidate drops totalUnits by exactly the realized bad debt. rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); From 1940aebb1dcb120ddd6ab4faa62dd0e57cf6777d Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 30 Jul 2026 20:41:42 +0200 Subject: [PATCH 120/159] Remove some require --- certora/specs/RealizableBadDebt.spec | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index d0eaa870f..0aadf8650 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -89,8 +89,9 @@ definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a > rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight.Market market, address borrower) filtered { f -> !f.isView && f.selector != sig:liquidate(Midnight.Market, uint256, uint256, uint256, address, bool, address, address, bytes).selector } { bytes32 id = summaryToId(market); - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require !liquidationLocked(id, borrower), "scope out the locked (re-entrant) seller case"; + // if seller is locked, they can create a position with bad debt. In that case the position + // must be healthy when the lock is removed later and no bad debt can be realized. + require !liquidationLocked(id, borrower), "scope out the re-entrant case"; require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; @@ -110,9 +111,6 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); - require market.collateralParams.length <= 2, "restrict collateralParams for loop tractability"; - require marketIsCreated(market), "market must be created (tickSpacing > 0)"; - require lossFactor(id) < max_uint128, "market lossFactor must not be saturated"; require debt(id, borrower) <= totalUnits(id), "position debt bounded by totalUnits"; uint256 badDebtBefore = realizableBadDebt(market, id, borrower); From 7360f87b33d2e11d33ad2d652596ac744044829c Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Fri, 31 Jul 2026 08:32:25 +0200 Subject: [PATCH 121/159] Remove the rules no longer needed --- certora/specs/MulDiv.spec | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 1900b79b0..2c3b2e783 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -83,29 +83,6 @@ rule mulDivAddUpUpTight(uint256 a1, uint256 a2, uint256 b, uint256 d) { assert mulDivUp(a1, b, d) + mulDivUp(a2, b, d) <= mulDivUp(a1plusa2, b, d) + 1; } -// Getter-form double-mulDivUp sub-additivity, with zero slack: for -// g(x) = mulDivUp(mulDivUp(x, p, S), W, L) (the per-collateral getter term, with L >= W), -// and s <= a, g(a) <= g(a - s) + g(s). -// Both ceil layers are sub-additive with zero slack (single-layer is mulDivAddUpUp above), and the -// composition carries the same zero slack: the inner ceil gives mulDivUp(a,p,S) <= mulDivUp(a-s,p,S) + -// mulDivUp(s,p,S) (a = (a-s) + s), then monotonicity + sub-additivity of the outer ceil close it. Used -// by RealizableBadDebtLiquidate.spec to bound the getter-sum drop g(c_k) - g(c_k - seized) by g(seized) -// on the single seized collateral, which is exactly the slack the loose single-layer axioms left open. -rule mulDivUpDoubleSubAdditive(uint256 a, uint256 s, uint256 p, uint256 S, uint256 W, uint256 L) { - require s <= a; - require S > 0 && W > 0 && L >= W; - - uint256 innerA = mulDivUp(a, p, S); - uint256 innerAS = mulDivUp(require_uint256(a - s), p, S); - uint256 innerS = mulDivUp(s, p, S); - - uint256 ga = mulDivUp(innerA, W, L); - uint256 gas = mulDivUp(innerAS, W, L); - uint256 gs = mulDivUp(innerS, W, L); - - assert ga <= gas + gs; -} - rule mulDivAddDownUp(uint256 a1, uint256 a2, uint256 b, uint256 d) { uint256 a1plusa2 = require_uint256(a1 + a2); assert mulDivDown(a1, b, d) + mulDivUp(a2, b, d) >= mulDivDown(a1plusa2, b, d); @@ -119,14 +96,6 @@ rule mulDivInverseUpDown(uint256 a, uint256 b, uint256 d) { assert mulDivUp(mulDivDown(a, b, d), d, b) <= a; } -// Getter-form seize valuation bound: valuing (up-up) the collateral that liquidate seizes (down-down) -// for repaidUnits r never exceeds r, when the seize and the valuation share the same factor l. -rule mulDivSeizeValueBounded(uint256 r, uint256 l, uint256 price, uint256 wad, uint256 scale) { - require l > 0 && price > 0 && wad > 0 && scale > 0; - uint256 seized = mulDivDown(mulDivDown(r, l, wad), scale, price); - assert mulDivUp(mulDivUp(seized, price, scale), wad, l) <= r; -} - rule mulDivArgumentLesserThanDenominator(uint256 a, uint256 b, uint256 d) { assert a <= d => mulDivDown(a, b, d) <= b; assert a <= d => mulDivUp(a, b, d) <= b; From dc3a82a2be54f0938c19527e4ded843e133ea9f9 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:31:04 +0200 Subject: [PATCH 122/159] Apply suggestions from code review Co-authored-by: Quentin Garchery Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- certora/specs/RealizableBadDebt.spec | 12 ++++-------- certora/specs/RealizableBadDebtLiquidate.spec | 4 ---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 0aadf8650..33493c4e1 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -11,7 +11,6 @@ methods { function realizableBadDebt(Midnight.Market, bytes32, address) external returns (uint256) envfree; function debt(bytes32, address) external returns (uint128) envfree; function totalUnits(bytes32) external returns (uint128) envfree; - function lossFactor(bytes32) external returns (uint128) envfree; function liquidationLocked(bytes32, address) external returns (bool) envfree; function tickSpacing(bytes32) external returns (uint8) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; @@ -19,9 +18,11 @@ methods { function _.price() external => summaryPrice(calledContract) expect(uint256); function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); + // Safe because the protocol doesn't use `toMarket` function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; - function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; + // Over-approximate the following functions. + function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); function maxLif(uint256 lltv, uint256 liquidationCursor) internal returns (uint256) => maxLifGhost(lltv, liquidationCursor); @@ -29,9 +30,6 @@ methods { // All external calls are assumed non-reentrant / non-reverting: we reason about the function bodies for safety properties. function SafeTransferLib.safeTransfer(address, address, uint256) internal => NONDET; function SafeTransferLib.safeTransferFrom(address, address, address, uint256) internal => NONDET; - function _.isRatified(Midnight.Offer, bytes, address) external => NONDET; - function _.canIncreaseCredit(address) external => NONDET; - function _.canIncreaseDebt(address) external => NONDET; function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; function _.onRepay(bytes32, Midnight.Market, uint256, address, bytes) external => NONDET; @@ -43,8 +41,6 @@ methods { definition WAD() returns uint256 = 10 ^ 18; -definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; - persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; @@ -111,7 +107,7 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight rule liquidateRealizesTotalUnits(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data) { bytes32 id = summaryToId(market); - require debt(id, borrower) <= totalUnits(id), "position debt bounded by totalUnits"; + require debt(id, borrower) <= totalUnits(id), "proven by totalUnitsEqualsSumNegativeDebtPlusWithdrawable"; uint256 badDebtBefore = realizableBadDebt(market, id, borrower); uint256 totalUnitsBefore = totalUnits(id); diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 6911c6b94..4d9fa4db0 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -9,10 +9,6 @@ methods { function multicall(bytes[]) external => HAVOC_ALL DELETE; function realizableBadDebt(Midnight.Market, bytes32, address) external returns (uint256) envfree; - function debt(bytes32, address) external returns (uint128) envfree; - function totalUnits(bytes32) external returns (uint128) envfree; - function lossFactor(bytes32) external returns (uint128) envfree; - function liquidationLocked(bytes32, address) external returns (bool) envfree; function tickSpacing(bytes32) external returns (uint8) envfree; function collateral(bytes32, address, uint256) external returns (uint128) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; From 6eba1a5e70a61ee89ec9253fb809e193cef0eabe Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:32:23 +0200 Subject: [PATCH 123/159] Apply suggestions from code review Co-authored-by: Quentin Garchery Co-authored-by: MathisGD <74971347+MathisGD@users.noreply.github.com> Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- certora/specs/RealizableBadDebtLiquidate.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 4d9fa4db0..2c55351e9 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -13,7 +13,7 @@ methods { function collateral(bytes32, address, uint256) external returns (uint128) envfree; function Utils.hashMarket(Midnight.Market) external returns (bytes32) envfree; - // Per-callee constant price (no price update); named so the rule can reference it, matching LiquidationBoundedByLIF.spec. + // No price update. function _.price() external => summaryPrice(calledContract) expect(uint256); function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); @@ -92,7 +92,7 @@ definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDiv // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). -definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); +definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 && a1 + a2 < 2^256 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(mulDivDown(a,b,d),d,b) <= a From 88ec1d4dcc87b7928abd3069a4cbd750c893fd50 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 1 Aug 2026 13:23:25 +0000 Subject: [PATCH 124/159] Inline axioms into rules and reference their MulDiv lemmas --- certora/specs/RealizableBadDebt.spec | 20 +++--- certora/specs/RealizableBadDebtLiquidate.spec | 66 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 33493c4e1..30055f5c0 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -18,10 +18,11 @@ methods { function _.price() external => summaryPrice(calledContract) expect(uint256); function IdLib.toId(Midnight.Market memory market) internal returns (bytes32) => summaryToId(market); + // Safe because the protocol doesn't use `toMarket` function IdLib.storeInCode(Midnight.Market memory) internal returns (address) => NONDET; - // Over-approximate the following functions. + // Over-approximate the following functions. function TickLib.tickToPrice(uint256 tick) internal returns (uint256) => NONDET; function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivDown(x, y, d); function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => summaryMulDivUp(x, y, d); @@ -73,12 +74,6 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } -definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); - -definition axiomUpGeqDown(mathint a, mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d); - -definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif); - /// RULES /// // No non-liquidate function may increase realizableBadDebt of a position. @@ -89,9 +84,14 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight // must be healthy when the lock is removed later and no bad debt can be realized. require !liquidationLocked(id, borrower), "scope out the re-entrant case"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d. axiomUpGeqDown(a, b, d), "axiom"; - require forall mathint a. forall mathint lif. forall mathint lltv. axiomLifLLTV(a, lif, lltv), "axiom"; + // mulDivUp is monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "mulDivUp is monotone in the first argument"; + + // mulDivUp is at least mulDivDown (proven in MulDiv.spec as mulDivUpGeqMulDivDown). + require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d), "mulDivUp is at least mulDivDown"; + + // If lltv * lif <= WAD^2 then mulDivUp(a, lltv, WAD) <= mulDivUp(a, WAD, lif). + require forall mathint a. forall mathint lif. forall mathint lltv. a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif), "if lltv * lif <= WAD^2 then mulDivUp(a, lltv, WAD) <= mulDivUp(a, WAD, lif)"; require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; uint256 badDebtBefore = realizableBadDebt(market, id, borrower); diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 2c55351e9..3999684c5 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -75,29 +75,6 @@ function marketIsCreated(Midnight.Market market) returns (bool) { return tickSpacing(summaryToId(market)) > 0; } -// Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). -definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); - -// Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB). -definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); - -// Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). -definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); - -// Monotone in the third argument (proven in MulDiv.spec as mulDivMonotoneD). -definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1); - -// Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). -definition axiomUpZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivUp(0, b, d) == 0; - -// proven in MulDiv.spec as mulDivAddUpUp: -// mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). -definition axiomAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 && a1 + a2 < 2^256 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d); - -// proven in MulDiv.spec as mulDivAddUpUp: -// mulDivUp(mulDivDown(a,b,d),d,b) <= a -definition axiomInverseUpDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a; - /// RULES /// // liquidate realizes the bad debt and doesn't create new bad debt: the recomputed realizable bad debt is exactly 0 after a liquidate. @@ -112,20 +89,43 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI seizedAssetsOut = seizedAssets; } else { seizedAssetsOut = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; - require axiomInverseUpDown(repaidUnits, maxLif, WAD()), "axiom"; - require axiomInverseUpDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; + + // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d), "axiom"; + + // Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB). + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d), "axiom"; + + // proven in MulDiv.spec as mulDivInverseUpDown: + // mulDivUp(mulDivDown(a,b,d),d,b) <= a + require repaidUnits >= 0 && maxLif > 0 && WAD() > 0 => ghostMulDivUp(ghostMulDivDown(repaidUnits, maxLif, WAD()), WAD(), maxLif) <= repaidUnits, "axiom"; + + // proven in MulDiv.spec as mulDivInverseUpDown: + // mulDivUp(mulDivDown(a,b,d),d,b) <= a + require ghostMulDivDown(repaidUnits, maxLif, WAD()) >= 0 && ORACLE_PRICE_SCALE() > 0 && price > 0 => ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), price, ORACLE_PRICE_SCALE()) <= ghostMulDivDown(repaidUnits, maxLif, WAD()), "axiom"; } mathint collateralAfter = collateral(id, borrower, collateralIndex) - seizedAssetsOut; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; - require axiomUpZero(price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomUpZero(WAD(), maxLif), "axiom"; - require axiomAddUpUp(collateralAfter, seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomAddUpUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; + // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "axiom"; + + // Monotone in the third argument (proven in MulDiv.spec as mulDivMonotoneD). + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1), "axiom"; + + // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). + require ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(0, price, ORACLE_PRICE_SCALE()) == 0, "axiom"; + + // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). + require maxLif > 0 => ghostMulDivUp(0, WAD(), maxLif) == 0, "axiom"; + + // proven in MulDiv.spec as mulDivAddUpUp: + // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). + require collateralAfter >= 0 && seizedAssetsOut >= 0 && price >= 0 && ORACLE_PRICE_SCALE() > 0 && collateralAfter + seizedAssetsOut < 2 ^ 256 => ghostMulDivUp(collateralAfter + seizedAssetsOut, price, ORACLE_PRICE_SCALE()) <= ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; + + // proven in MulDiv.spec as mulDivAddUpUp: + // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). + require ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) >= 0 && ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) >= 0 && WAD() >= 0 && maxLif > 0 && ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) < 2 ^ 256 => ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) <= ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) + ghostMulDivUp(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From 4a863031e3a7f6d748bcd54b7e7ded02b874a1a1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 1 Aug 2026 13:30:21 +0000 Subject: [PATCH 125/159] Prove liquidate does not increase another position's realizable bad debt --- certora/specs/RealizableBadDebtLiquidate.spec | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 3999684c5..cbc19bacb 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -131,3 +131,17 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI assert realizableBadDebt(market, id, borrower) == 0; } + +// liquidating one position does not increase the realizable bad debt of a different position. +rule liquidateDoesNotIncreaseOtherRealizableBadDebt(env e, Midnight.Market market, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bool postMaturityMode, address receiver, address callback, bytes data, Midnight.Market measuredMarket, address measuredBorrower) { + bytes32 id = summaryToId(market); + bytes32 measuredId = summaryToId(measuredMarket); + + require measuredId != id || measuredBorrower != borrower; + + uint256 rbdBefore = realizableBadDebt(measuredMarket, measuredId, measuredBorrower); + + liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); + + assert realizableBadDebt(measuredMarket, measuredId, measuredBorrower) <= rbdBefore; +} From c60091c39e642237e271535350eb5572d4f00ac4 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 1 Aug 2026 13:41:17 +0000 Subject: [PATCH 126/159] Fix inlined axiomAddUpUp antecedent to match original --- certora/specs/RealizableBadDebtLiquidate.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index cbc19bacb..10f06244f 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -121,11 +121,11 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). - require collateralAfter >= 0 && seizedAssetsOut >= 0 && price >= 0 && ORACLE_PRICE_SCALE() > 0 && collateralAfter + seizedAssetsOut < 2 ^ 256 => ghostMulDivUp(collateralAfter + seizedAssetsOut, price, ORACLE_PRICE_SCALE()) <= ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; + require collateralAfter >= 0 && seizedAssetsOut >= 0 && price >= 0 && ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(collateralAfter + seizedAssetsOut, price, ORACLE_PRICE_SCALE()) <= ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; // proven in MulDiv.spec as mulDivAddUpUp: // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). - require ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) >= 0 && ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) >= 0 && WAD() >= 0 && maxLif > 0 && ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) < 2 ^ 256 => ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) <= ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) + ghostMulDivUp(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; + require ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) >= 0 && ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) >= 0 && WAD() >= 0 && maxLif > 0 => ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) <= ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) + ghostMulDivUp(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From f10a7bd0cbd472d96b52bb8e473cc9e8796c91b8 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:09:13 +0200 Subject: [PATCH 127/159] Update certora/confs/RealizableBadDebt.conf Co-authored-by: Quentin Garchery Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- certora/confs/RealizableBadDebt.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/certora/confs/RealizableBadDebt.conf b/certora/confs/RealizableBadDebt.conf index df2e0984e..41cd4fc6f 100644 --- a/certora/confs/RealizableBadDebt.conf +++ b/certora/confs/RealizableBadDebt.conf @@ -24,6 +24,5 @@ "-timeout 7200", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5},z3:def{randomSeed=6},z3:def{randomSeed=7},z3:def{randomSeed=8},z3:def{randomSeed=9},z3:def{randomSeed=10}]" ], - "smt_timeout": 7200, "msg": "Midnight: realizable bad debt" } From 8300f7c99874a1da019e9eb14cd5e6c69eb8cdc4 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:09:21 +0200 Subject: [PATCH 128/159] Update certora/confs/RealizableBadDebtLiquidate.conf Co-authored-by: Quentin Garchery Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- certora/confs/RealizableBadDebtLiquidate.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/certora/confs/RealizableBadDebtLiquidate.conf b/certora/confs/RealizableBadDebtLiquidate.conf index 5d403855d..93b57b64a 100644 --- a/certora/confs/RealizableBadDebtLiquidate.conf +++ b/certora/confs/RealizableBadDebtLiquidate.conf @@ -24,6 +24,5 @@ "-timeout 1800", "-s [cvc5:def{randomSeed=1},cvc5:def{randomSeed=2},cvc5:def{randomSeed=3},z3:def]" ], - "smt_timeout": 1800, "msg": "Midnight: realizable bad debt (liquidate)" } From aeac0d0efbcbedf66cd3d179fa5b3dd01872774f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 10:21:11 +0000 Subject: [PATCH 129/159] Use general forall form for inlined axiom requires --- certora/specs/RealizableBadDebt.spec | 9 ++--- certora/specs/RealizableBadDebtLiquidate.spec | 34 ++++++------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/certora/specs/RealizableBadDebt.spec b/certora/specs/RealizableBadDebt.spec index 30055f5c0..65fdb8965 100644 --- a/certora/specs/RealizableBadDebt.spec +++ b/certora/specs/RealizableBadDebt.spec @@ -84,14 +84,11 @@ rule realizableBadDebtCannotIncrease(env e, method f, calldataarg args, Midnight // must be healthy when the lock is removed later and no bad debt can be realized. require !liquidationLocked(id, borrower), "scope out the re-entrant case"; - // mulDivUp is monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "mulDivUp is monotone in the first argument"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA)"; - // mulDivUp is at least mulDivDown (proven in MulDiv.spec as mulDivUpGeqMulDivDown). - require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d), "mulDivUp is at least mulDivDown"; + require forall mathint a. forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(a, b, d) >= ghostMulDivDown(a, b, d), "Rounding up is at least rounding down (proven in MulDiv.spec as mulDivUpGeqMulDivDown)"; - // If lltv * lif <= WAD^2 then mulDivUp(a, lltv, WAD) <= mulDivUp(a, WAD, lif). - require forall mathint a. forall mathint lif. forall mathint lltv. a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif), "if lltv * lif <= WAD^2 then mulDivUp(a, lltv, WAD) <= mulDivUp(a, WAD, lif)"; + require forall mathint a. forall mathint lif. forall mathint lltv. a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif), "maxLif is at most 1/lltv"; require forall uint256 lltv. forall uint256 cursor. lltv * maxLifGhost(lltv, cursor) <= WAD() * WAD(), "maxLif is at most 1/lltv"; uint256 badDebtBefore = realizableBadDebt(market, id, borrower); diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 10f06244f..7539cbad8 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -90,42 +90,28 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI } else { seizedAssetsOut = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price); - // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d), "Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA)"; - // Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB). - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d), "Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB)"; - // proven in MulDiv.spec as mulDivInverseUpDown: - // mulDivUp(mulDivDown(a,b,d),d,b) <= a - require repaidUnits >= 0 && maxLif > 0 && WAD() > 0 => ghostMulDivUp(ghostMulDivDown(repaidUnits, maxLif, WAD()), WAD(), maxLif) <= repaidUnits, "axiom"; + require forall mathint a. forall mathint b. forall mathint d. a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a, "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; - // proven in MulDiv.spec as mulDivInverseUpDown: - // mulDivUp(mulDivDown(a,b,d),d,b) <= a - require ghostMulDivDown(repaidUnits, maxLif, WAD()) >= 0 && ORACLE_PRICE_SCALE() > 0 && price > 0 => ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), price, ORACLE_PRICE_SCALE()) <= ghostMulDivDown(repaidUnits, maxLif, WAD()), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a, "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; } mathint collateralAfter = collateral(id, borrower, collateralIndex) - seizedAssetsOut; - // Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA). - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d), "Monotone in the first argument (proven in MulDiv.spec as mulDivMonotoneA)"; - // Monotone in the third argument (proven in MulDiv.spec as mulDivMonotoneD). - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1), "Antitone in the denominator (proven in MulDiv.spec as mulDivMonotoneD)"; - // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). - require ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(0, price, ORACLE_PRICE_SCALE()) == 0, "axiom"; + require forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(0, b, d) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; - // Zero collateral values to zero (proven in MulDiv.spec as mulDivZero). - require maxLif > 0 => ghostMulDivUp(0, WAD(), maxLif) == 0, "axiom"; + require forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(0, b, d) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; - // proven in MulDiv.spec as mulDivAddUpUp: - // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). - require collateralAfter >= 0 && seizedAssetsOut >= 0 && price >= 0 && ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(collateralAfter + seizedAssetsOut, price, ORACLE_PRICE_SCALE()) <= ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; - // proven in MulDiv.spec as mulDivAddUpUp: - // mulDivUp(a1 + a2, b, d) <= mulDivUp(a1, b, d) + mulDivUp(a2, b, d). - require ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) >= 0 && ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) >= 0 && WAD() >= 0 && maxLif > 0 => ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) <= ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) + ghostMulDivUp(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From 18f8179e33bb8a1d0d868f4115737eea31459e92 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 10:34:06 +0000 Subject: [PATCH 130/159] Pin AddUpUp/InverseUpDown/UpZero axioms to call args (forall form times out) --- certora/specs/RealizableBadDebtLiquidate.spec | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/certora/specs/RealizableBadDebtLiquidate.spec b/certora/specs/RealizableBadDebtLiquidate.spec index 7539cbad8..7fbf8225c 100644 --- a/certora/specs/RealizableBadDebtLiquidate.spec +++ b/certora/specs/RealizableBadDebtLiquidate.spec @@ -94,9 +94,9 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d), "Monotone in the second argument (proven in MulDiv.spec as mulDivMonotoneB)"; - require forall mathint a. forall mathint b. forall mathint d. a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a, "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; + require repaidUnits >= 0 && maxLif > 0 && WAD() > 0 => ghostMulDivUp(ghostMulDivDown(repaidUnits, maxLif, WAD()), WAD(), maxLif) <= repaidUnits, "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; - require forall mathint a. forall mathint b. forall mathint d. a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a, "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; + require ghostMulDivDown(repaidUnits, maxLif, WAD()) >= 0 && ORACLE_PRICE_SCALE() > 0 && price > 0 => ghostMulDivUp(ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price), price, ORACLE_PRICE_SCALE()) <= ghostMulDivDown(repaidUnits, maxLif, WAD()), "Round-trip up-after-down is bounded (proven in MulDiv.spec as mulDivInverseUpDown)"; } mathint collateralAfter = collateral(id, borrower, collateralIndex) - seizedAssetsOut; @@ -105,13 +105,13 @@ rule liquidateRealizesBadDebt(env e, Midnight.Market market, uint256 collateralI require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d2) <= ghostMulDivUp(a, b, d1), "Antitone in the denominator (proven in MulDiv.spec as mulDivMonotoneD)"; - require forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(0, b, d) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; + require ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(0, price, ORACLE_PRICE_SCALE()) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; - require forall mathint b. forall mathint d. d > 0 => ghostMulDivUp(0, b, d) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; + require maxLif > 0 => ghostMulDivUp(0, WAD(), maxLif) == 0, "Zero numerator gives zero (proven in MulDiv.spec as mulDivZero)"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; + require collateralAfter >= 0 && seizedAssetsOut >= 0 && price >= 0 && ORACLE_PRICE_SCALE() > 0 => ghostMulDivUp(collateralAfter + seizedAssetsOut, price, ORACLE_PRICE_SCALE()) <= ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivUp(a1 + a2, b, d) <= ghostMulDivUp(a1, b, d) + ghostMulDivUp(a2, b, d), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; + require ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) >= 0 && ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()) >= 0 && WAD() >= 0 && maxLif > 0 => ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()) + ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) <= ghostMulDivUp(ghostMulDivUp(collateralAfter, price, ORACLE_PRICE_SCALE()), WAD(), maxLif) + ghostMulDivUp(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), WAD(), maxLif), "Sub-additive in the numerator (proven in MulDiv.spec as mulDivAddUpUp)"; liquidate(e, market, collateralIndex, seizedAssets, repaidUnits, borrower, postMaturityMode, receiver, callback, data); From 8ea01557493cf5d3b66714d2ba6240fa7ec6dacf Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 10:21:25 +0000 Subject: [PATCH 131/159] Test: make ERC20NoReturn.approve genuinely return nothing `ERC20NoReturn.approve` was declared `returns (bool)` and returned `true`, so the TOKEN_TYPE=4 ("no-return") matrix leg only exercised no-return `transfer`/`transferFrom` and never a void `approve`. Voiding the mock's `approve` makes every high-level `approve` call declared `returns (bool)` revert on solc's returndatasize check, so test approvals on matrix tokens now go through `ERC20Lib.safeApprove`, which accepts empty-or- `true` returndata. All five matrix mocks return `true` unconditionally (USDT reverts, never returns `false`), so this is behaviour-preserving; the `require` wrappers dropped in BlueBuyCallbackIntegrationTest were never falsifiable and `safeApprove` retains the equivalent check. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TFq2E5QUuD8fSDyvpQ6BkQ --- test/AuthorizationTest.sol | 13 +++++++------ test/BaseTest.sol | 23 ++++++++++++----------- test/BlueBuyCallbackIntegrationTest.sol | 11 ++++++----- test/OtherFunctionsTest.sol | 7 ++++--- test/TakeTest.sol | 14 +++++++------- test/erc20s/ERC20NoReturn.sol | 4 ++-- 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/test/AuthorizationTest.sol b/test/AuthorizationTest.sol index a1efa31b1..041102203 100644 --- a/test/AuthorizationTest.sol +++ b/test/AuthorizationTest.sol @@ -8,6 +8,7 @@ import {UtilsLib} from "../src/libraries/UtilsLib.sol"; import {ERC20} from "./erc20s/ERC20.sol"; import {MAX_TICK} from "../src/libraries/TickLib.sol"; import {EventsLib} from "../src/libraries/EventsLib.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; contract AuthorizationTest is BaseTest { using UtilsLib for uint256; @@ -83,7 +84,7 @@ contract AuthorizationTest is BaseTest { deal(collateralToken, user, collateralAmount); vm.prank(user); - ERC20(collateralToken).approve(address(midnight), collateralAmount); + ERC20Lib.safeApprove(collateralToken, address(midnight), collateralAmount); vm.prank(user); midnight.supplyCollateral(market, 0, collateralAmount, user); @@ -131,7 +132,7 @@ contract AuthorizationTest is BaseTest { deal(collateralToken, user, collateralAmount); vm.prank(user); - ERC20(collateralToken).approve(address(midnight), collateralAmount); + ERC20Lib.safeApprove(collateralToken, address(midnight), collateralAmount); vm.prank(user); midnight.supplyCollateral(market, 0, collateralAmount, user); @@ -151,7 +152,7 @@ contract AuthorizationTest is BaseTest { deal(collateralToken, operator, collateralAmount); vm.prank(operator); - ERC20(collateralToken).approve(address(midnight), collateralAmount); + ERC20Lib.safeApprove(collateralToken, address(midnight), collateralAmount); vm.prank(operator); vm.expectRevert(IMidnight.Unauthorized.selector); @@ -192,7 +193,7 @@ contract AuthorizationTest is BaseTest { deal(collateralToken, user, collateralAmount); vm.prank(user); - ERC20(collateralToken).approve(address(midnight), collateralAmount); + ERC20Lib.safeApprove(collateralToken, address(midnight), collateralAmount); vm.prank(user); midnight.supplyCollateral(market, 0, collateralAmount, user); @@ -263,9 +264,9 @@ contract AuthorizationTest is BaseTest { deal(address(loanToken), authorized, units); vm.prank(authorized); - loanToken.approve(address(midnight), 0); + ERC20Lib.safeApprove(address(loanToken), address(midnight), 0); vm.prank(authorized); - loanToken.approve(address(midnight), units); + ERC20Lib.safeApprove(address(loanToken), address(midnight), units); vm.prank(authorized); vm.expectRevert(IMidnight.Unauthorized.selector); diff --git a/test/BaseTest.sol b/test/BaseTest.sol index 58c90cd61..ba9b1d29f 100644 --- a/test/BaseTest.sol +++ b/test/BaseTest.sol @@ -27,6 +27,7 @@ import {Market, Offer, CollateralParams} from "../src/interfaces/IMidnight.sol"; import {Midnight} from "../src/Midnight.sol"; import {EcrecoverRatifier} from "../src/ratifiers/EcrecoverRatifier.sol"; import {EcrecoverAuthorizer} from "../src/periphery/ecrecover-authorizer/EcrecoverAuthorizer.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; uint256 constant MAX_TEST_AMOUNT = type(uint128).max; /// @dev The default LLTV enabled in tests. @@ -128,19 +129,19 @@ abstract contract BaseTest is Test { oracle2 = new Oracle(); vm.prank(lender); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); vm.prank(otherLender); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); vm.prank(borrower); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); vm.prank(otherBorrower); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); vm.prank(liquidator); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); - loanToken.approve(address(midnight), type(uint256).max); - collateralToken1.approve(address(midnight), type(uint256).max); - collateralToken2.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(collateralToken1), address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(collateralToken2), address(midnight), type(uint256).max); } // helpers. @@ -156,8 +157,8 @@ abstract contract BaseTest is Test { deal(address(market.collateralParams[collateralIndex].token), _borrower, collateral); vm.startPrank(_borrower); - ERC20(market.collateralParams[collateralIndex].token).approve(address(midnight), 0); - ERC20(market.collateralParams[collateralIndex].token).approve(address(midnight), collateral); + ERC20Lib.safeApprove(market.collateralParams[collateralIndex].token, address(midnight), 0); + ERC20Lib.safeApprove(market.collateralParams[collateralIndex].token, address(midnight), collateral); midnight.supplyCollateral(market, collateralIndex, collateral, _borrower); vm.stopPrank(); } @@ -195,7 +196,7 @@ abstract contract BaseTest is Test { privateKey[badBorrower] = badBorrowerPrivateKey; address unluckyLender = makeAddr("unluckyLender"); vm.prank(unluckyLender); - loanToken.approve(address(midnight), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(midnight), type(uint256).max); Offer memory badBorrowerOffer; badBorrowerOffer.market = market; badBorrowerOffer.buy = false; diff --git a/test/BlueBuyCallbackIntegrationTest.sol b/test/BlueBuyCallbackIntegrationTest.sol index b6dd42b9c..dc5548c4e 100644 --- a/test/BlueBuyCallbackIntegrationTest.sol +++ b/test/BlueBuyCallbackIntegrationTest.sol @@ -9,6 +9,7 @@ import {MAX_TICK} from "../src/libraries/TickLib.sol"; import {UtilsLib} from "../src/libraries/UtilsLib.sol"; import {BlueBuyCallback} from "../src/periphery/blue-buy-callback/BlueBuyCallback.sol"; import {BlueBuyCallbackFactory} from "../src/periphery/blue-buy-callback/BlueBuyCallbackFactory.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; import {BaseTest, LLTV, LIQUIDATION_CURSOR} from "./BaseTest.sol"; contract BlueBuyCallbackIntegrationTest is BaseTest { @@ -61,7 +62,7 @@ contract BlueBuyCallbackIntegrationTest is BaseTest { function testBuyUsesLiquiditySuppliedOnBlue(uint256 units) public { units = bound(units, 1, 1e30); deal(address(loanToken), address(this), units); - require(loanToken.approve(address(blue), units)); + ERC20Lib.safeApprove(address(loanToken), address(blue), units); (uint256 suppliedAssets, uint256 suppliedShares) = blue.supply(blueMarketParams, units, 0, address(callback), hex""); assertEq(suppliedAssets, units); @@ -95,12 +96,12 @@ contract BlueBuyCallbackIntegrationTest is BaseTest { suppliedAssets = bound(suppliedAssets, 2, 1e30); borrowedAssets = bound(borrowedAssets, 1, suppliedAssets / 2); deal(address(loanToken), address(this), suppliedAssets); - require(loanToken.approve(address(blue), suppliedAssets)); + ERC20Lib.safeApprove(address(loanToken), address(blue), suppliedAssets); blue.supply(blueMarketParams, suppliedAssets, 0, address(callback), hex""); deal(address(collateralToken1), borrower, borrowedAssets * 2); vm.startPrank(borrower); - require(collateralToken1.approve(address(blue), borrowedAssets * 2)); + ERC20Lib.safeApprove(address(collateralToken1), address(blue), borrowedAssets * 2); blue.supplyCollateral(blueMarketParams, borrowedAssets * 2, borrower, hex""); blue.borrow(blueMarketParams, borrowedAssets, 0, borrower, borrower); vm.stopPrank(); @@ -114,7 +115,7 @@ contract BlueBuyCallbackIntegrationTest is BaseTest { suppliedAssets = bound(suppliedAssets, 1, 1e30); flashloanedAssets = bound(flashloanedAssets, 1, suppliedAssets); deal(address(loanToken), address(this), suppliedAssets); - require(loanToken.approve(address(blue), suppliedAssets)); + ERC20Lib.safeApprove(address(loanToken), address(blue), suppliedAssets); blue.supply(blueMarketParams, suppliedAssets, 0, address(callback), hex""); assertEq(callback.buyerAssetsBound(bytes32(0), market, lender, abi.encode(blueMarketParams)), suppliedAssets); @@ -126,6 +127,6 @@ contract BlueBuyCallbackIntegrationTest is BaseTest { function onMorphoFlashLoan(uint256 assets, bytes calldata) external { observedBound = callback.buyerAssetsBound(bytes32(0), market, lender, abi.encode(blueMarketParams)); - require(loanToken.approve(address(blue), assets)); + ERC20Lib.safeApprove(address(loanToken), address(blue), assets); } } diff --git a/test/OtherFunctionsTest.sol b/test/OtherFunctionsTest.sol index ea131bc14..e61f10261 100644 --- a/test/OtherFunctionsTest.sol +++ b/test/OtherFunctionsTest.sol @@ -13,6 +13,7 @@ import { import {Midnight} from "../src/Midnight.sol"; import {IdLib} from "../src/libraries/IdLib.sol"; import {EventsLib} from "../src/libraries/EventsLib.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; import {ERC20} from "./erc20s/ERC20.sol"; import {Oracle} from "./helpers/Oracle.sol"; @@ -155,7 +156,7 @@ contract OtherFunctionsTest is BaseTest { vm.prank(borrower); midnight.setIsAuthorized(caller, true, borrower); vm.prank(address(callback)); - loanToken.approve(address(midnight), repaid); + ERC20Lib.safeApprove(address(loanToken), address(midnight), repaid); vm.prank(caller); midnight.repay(market, repaid, borrower, address(callback), data); @@ -178,7 +179,7 @@ contract OtherFunctionsTest is BaseTest { address callback = address(new InvalidRepayCallback()); deal(address(loanToken), callback, repaid); vm.prank(callback); - loanToken.approve(address(midnight), repaid); + ERC20Lib.safeApprove(address(loanToken), address(midnight), repaid); vm.expectRevert(IMidnight.WrongRepayCallbackReturnValue.selector); vm.prank(borrower); @@ -828,7 +829,7 @@ contract RepayCallback { function repay(Midnight midnight, Market memory market, uint256 units, address onBehalf, bytes memory data) external { - ERC20(market.loanToken).approve(address(midnight), units); + ERC20Lib.safeApprove(market.loanToken, address(midnight), units); midnight.repay(market, units, onBehalf, address(this), data); } diff --git a/test/TakeTest.sol b/test/TakeTest.sol index fbb1718d7..c4f32592e 100644 --- a/test/TakeTest.sol +++ b/test/TakeTest.sol @@ -11,8 +11,8 @@ import {IBuyCallback, ISellCallback} from "../src/interfaces/ICallbacks.sol"; import {IRatifier} from "../src/interfaces/IRatifier.sol"; import {IdLib} from "../src/libraries/IdLib.sol"; import {EventsLib} from "../src/libraries/EventsLib.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; import {BaseTest, LLTV, LIQUIDATION_CURSOR} from "./BaseTest.sol"; -import {ERC20} from "./erc20s/ERC20.sol"; import {Oracle} from "./helpers/Oracle.sol"; import {StdStorage, stdStorage} from "../lib/forge-std/src/StdStorage.sol"; @@ -1591,7 +1591,7 @@ contract BorrowCallback is ISellCallback { recordedPendingFeeDecrease = pendingFeeDecrease; (uint256 collateralIndex, uint256 amount,) = abi.decode(data, (uint256, uint256, bytes)); address collateralToken = market.collateralParams[collateralIndex].token; - ERC20(collateralToken).approve(msg.sender, amount); + ERC20Lib.safeApprove(collateralToken, msg.sender, amount); Midnight(msg.sender).supplyCollateral(market, collateralIndex, amount, seller); return CALLBACK_SUCCESS; } @@ -1619,13 +1619,13 @@ contract ReentrantLiquidateBorrowCallback is ISellCallback { (uint256 collateralIndex, uint256 collateralAmount, uint256 repaidUnits) = abi.decode(data, (uint256, uint256, uint256)); address collateralToken = market.collateralParams[collateralIndex].token; - ERC20(collateralToken).approve(msg.sender, collateralAmount); + ERC20Lib.safeApprove(collateralToken, msg.sender, collateralAmount); Midnight(msg.sender).supplyCollateral(market, collateralIndex, collateralAmount, seller); Oracle oracle = Oracle(market.collateralParams[collateralIndex].oracle); uint256 healthyPrice = oracle.price(); oracle.setPrice(healthyPrice / 2); - ERC20(market.loanToken).approve(msg.sender, repaidUnits); + ERC20Lib.safeApprove(market.loanToken, msg.sender, repaidUnits); try Midnight(msg.sender) .liquidate(market, collateralIndex, 0, repaidUnits, seller, false, address(this), address(0), "") returns ( uint256, uint256 @@ -1676,7 +1676,7 @@ contract NestedTakeReentrantLiquidateCallback is ISellCallback { if (!reentered) { uint256 idx = storedCollateralIndex; address collateralToken = market.collateralParams[idx].token; - ERC20(collateralToken).approve(msg.sender, storedCollateralAmount); + ERC20Lib.safeApprove(collateralToken, msg.sender, storedCollateralAmount); Midnight(msg.sender).supplyCollateral(market, idx, storedCollateralAmount, seller); reentered = true; @@ -1686,7 +1686,7 @@ contract NestedTakeReentrantLiquidateCallback is ISellCallback { Oracle oracle = Oracle(market.collateralParams[idx].oracle); uint256 healthyPrice = oracle.price(); oracle.setPrice(healthyPrice / 2); - ERC20(market.loanToken).approve(msg.sender, storedRepaidUnits); + ERC20Lib.safeApprove(market.loanToken, msg.sender, storedRepaidUnits); try Midnight(msg.sender) .liquidate(market, idx, 0, storedRepaidUnits, seller, false, address(this), address(0), "") returns ( uint256, uint256 @@ -1729,7 +1729,7 @@ contract LendCallback is IBuyCallback { recordedUnits = units; recordedData = data; recordedPendingFeeIncrease = pendingFeeIncrease; - ERC20(market.loanToken).approve(msg.sender, buyerAssets); + ERC20Lib.safeApprove(market.loanToken, msg.sender, buyerAssets); return CALLBACK_SUCCESS; } diff --git a/test/erc20s/ERC20NoReturn.sol b/test/erc20s/ERC20NoReturn.sol index 849e68b26..2494fe126 100644 --- a/test/erc20s/ERC20NoReturn.sol +++ b/test/erc20s/ERC20NoReturn.sol @@ -29,8 +29,8 @@ contract ERC20NoReturn is PermitExt { _transfer(_from, _to, _amount); } - function approve(address _spender, uint256 _amount) public returns (bool) { + /// @dev Declares no return value, so approvals on this token must go through `ERC20Lib.safeApprove`. + function approve(address _spender, uint256 _amount) public { allowance[msg.sender][_spender] = _amount; - return true; } } From 7997fc520cd8b5953e12c90ed54adcd563c91105 Mon Sep 17 00:00:00 2001 From: MathisGD <74971347+MathisGD@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:53:21 +0200 Subject: [PATCH 132/159] Apply suggestion from @MathisGD Signed-off-by: MathisGD <74971347+MathisGD@users.noreply.github.com> --- test/erc20s/ERC20NoReturn.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/test/erc20s/ERC20NoReturn.sol b/test/erc20s/ERC20NoReturn.sol index 2494fe126..f7641a401 100644 --- a/test/erc20s/ERC20NoReturn.sol +++ b/test/erc20s/ERC20NoReturn.sol @@ -29,7 +29,6 @@ contract ERC20NoReturn is PermitExt { _transfer(_from, _to, _amount); } - /// @dev Declares no return value, so approvals on this token must go through `ERC20Lib.safeApprove`. function approve(address _spender, uint256 _amount) public { allowance[msg.sender][_spender] = _amount; } From 314b9139afeb75d8a4c06c3918fea2a25f3adc04 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 08:24:15 +0000 Subject: [PATCH 133/159] [tests] BlueFallbackRolling: safe approve on loan token Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HC6jESoBGvyJkzKEwm3n9t --- test/BlueFallbackRollingTest.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index 758319abf..fb8012eac 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -9,6 +9,7 @@ import {Market, CollateralParams} from "../src/interfaces/IMidnight.sol"; import {WAD} from "../src/libraries/ConstantsLib.sol"; import {BlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol"; import {IBlueFallbackRolling} from "../src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol"; +import {ERC20Lib} from "../src/periphery/libraries/ERC20Lib.sol"; import {BaseTest, LLTV, LIQUIDATION_CURSOR} from "./BaseTest.sol"; contract BlueFallbackRollingTest is BaseTest { @@ -81,7 +82,7 @@ contract BlueFallbackRollingTest is BaseTest { setupMarket(midnightMarket, DEBT); deal(address(loanToken), address(this), 2 * DEBT); - loanToken.approve(address(blue), type(uint256).max); + ERC20Lib.safeApprove(address(loanToken), address(blue), type(uint256).max); blue.supply(blueMarketParams, 2 * DEBT, 0, lender, hex""); vm.prank(borrower); From 86551f6dd6bf47bca8e6451d5a28c129bab10b48 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 08:34:12 +0000 Subject: [PATCH 134/159] Port NONDET summaries for tickToPrice and mulDiv to ReentrancyView spec --- certora/specs/ReentrancyView.spec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/certora/specs/ReentrancyView.spec b/certora/specs/ReentrancyView.spec index d740d00af..bb7c7b4e8 100644 --- a/certora/specs/ReentrancyView.spec +++ b/certora/specs/ReentrancyView.spec @@ -8,6 +8,11 @@ methods { // valid even if they changed the state. function touchMarket(Midnight.Market memory) internal returns (bytes32) => NONDET; function _updatePosition(Midnight.Market memory, bytes32, address) internal returns (uint128, uint128, uint128) => NONDET; + + // These functions are over-approximated, except for the reverting behavior. We don't look at the reverting behavior in this file. + function TickLib.tickToPrice(uint256) internal returns (uint256) => NONDET; + function UtilsLib.mulDivDown(uint256 x, uint256 y, uint256 d) internal returns (uint256) => NONDET; + function UtilsLib.mulDivUp(uint256 x, uint256 y, uint256 d) internal returns (uint256) => NONDET; } // True when at least one slot was written. From aef0c2a0857aa9c90625eac35464439465bb3dd8 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Wed, 5 Aug 2026 18:06:05 +0200 Subject: [PATCH 135/159] Separate MulDiv axiom spec file --- certora/specs/Healthiness.spec | 54 +++-------- certora/specs/MulDiv.spec | 5 + certora/specs/MulDivAxioms.spec | 92 +++++++++++++++++++ .../specs/TakeAmountsLibInvertibility.spec | 36 +++----- 4 files changed, 124 insertions(+), 63 deletions(-) create mode 100644 certora/specs/MulDivAxioms.spec diff --git a/certora/specs/Healthiness.spec b/certora/specs/Healthiness.spec index 6b5506804..4c794859f 100644 --- a/certora/specs/Healthiness.spec +++ b/certora/specs/Healthiness.spec @@ -2,6 +2,7 @@ // Copyright (c) 2026 Morpho Association import "BitmapSummaries.spec"; +import "MulDivAxioms.spec"; using Havoc as havocCallback; @@ -51,35 +52,6 @@ definition ORACLE_PRICE_SCALE() returns uint256 = 10 ^ 36; persistent ghost summaryPrice(address) returns uint256; -persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; - -persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; - -/* Axioms that are proved by MulDiv.spec */ - -/* proved in mulDivZero in MulDiv.spec */ -definition axiomDownZero(mathint b, mathint d) returns bool = d > 0 => ghostMulDivDown(0, b, d) == 0; - -/* proved in mulDivMonotoneA */ -definition axiomDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivDown(a1, b, d) <= ghostMulDivDown(a2, b, d); - -definition axiomUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = 0 <= a1 && a1 <= a2 && 0 <= b && 0 < d => ghostMulDivUp(a1, b, d) <= ghostMulDivUp(a2, b, d); - -/* proved in mulDivMonotoneB */ -definition axiomDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = 0 <= a && 0 <= b1 && b1 <= b2 && 0 < d => ghostMulDivDown(a, b1, d) <= ghostMulDivDown(a, b2, d); - -/* proved in mulDivMonotoneD */ -definition axiomUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = 0 <= a && 0 <= b && 0 < d1 && d1 <= d2 => ghostMulDivUp(a, b, d1) >= ghostMulDivUp(a, b, d2); - -/* proved in mulDivAddDownUp */ -definition axiomAddDownUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => ghostMulDivDown(a1, b, d) + ghostMulDivUp(a2, b, d) >= ghostMulDivDown(a1 + a2, b, d); - -/* proved in mulDivInverseUpDown */ -definition axiomInverseUpDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b > 0 && d > 0 => ghostMulDivUp(ghostMulDivDown(a, b, d), d, b) <= a; - -/* proved in ExactMath.spec (mulDivLifLLTV) */ -definition axiomLifLLTV(mathint a, mathint lif, mathint lltv) returns bool = a >= 0 && lltv * lif <= WAD() * WAD() => ghostMulDivUp(a, lltv, WAD()) <= ghostMulDivUp(a, WAD(), lif); - function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { bool overflow; if (overflow || d == 0) { @@ -270,17 +242,17 @@ rule stayHealthyLiquidateSameBorrower(env e, uint256 collateralIndex, uint256 se mathint price = summaryPrice(globalMarket.collateralParams[collateralIndex].oracle); // require all the axioms that are needed to prove the healthiness after liquidation. These are the same axioms that are proved in the MulDiv.spec - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "axiom"; - require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomDownMonotoneB(a, b1, b2, d), "axiom"; - require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomUpMonotoneD(a, b, d1, d2), "axiom"; - require axiomDownZero(price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomDownZero(globalMarketCollateralLLTV[collateralIndex], WAD()), "axiom"; - require axiomInverseUpDown(repaidUnitsOut, maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), WAD()), "axiom"; - require axiomInverseUpDown(ghostMulDivDown(repaidUnitsOut, maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; - require axiomLifLLTV(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), globalMarketCollateralLLTV[collateralIndex]), "axiom"; - require axiomAddDownUp(collateralAfter, seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; - require axiomAddDownUp(ghostMulDivDown(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), globalMarketCollateralLLTV[collateralIndex], WAD()), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomMathMulDivDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomMathMulDivUpMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a. forall mathint b1. forall mathint b2. forall mathint d. axiomMathMulDivDownMonotoneB(a, b1, b2, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d1. forall mathint d2. axiomMathMulDivUpMonotoneD(a, b, d1, d2), "axiom"; + require axiomMathMulDivDownZeroA(price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomMathMulDivDownZeroA(globalMarketCollateralLLTV[collateralIndex], WAD()), "axiom"; + require axiomMathMulDivInverseUpDown(repaidUnitsOut, maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), WAD()), "axiom"; + require axiomMathMulDivInverseUpDown(ghostMulDivDown(repaidUnitsOut, maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), WAD()), ORACLE_PRICE_SCALE(), price), "axiom"; + require axiomMathMulDivUpMonotoneBD(ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), maxLifGhost(globalMarketCollateralLLTV[collateralIndex], globalMarketCollateralLiquidationCursor[collateralIndex]), WAD(), WAD(), globalMarketCollateralLLTV[collateralIndex]), "axiom"; + require axiomMathMulDivAddDownUp(collateralAfter, seizedAssetsOut, price, ORACLE_PRICE_SCALE()), "axiom"; + require axiomMathMulDivAddDownUp(ghostMulDivDown(collateralAfter, price, ORACLE_PRICE_SCALE()), ghostMulDivUp(seizedAssetsOut, price, ORACLE_PRICE_SCALE()), globalMarketCollateralLLTV[collateralIndex], WAD()), "axiom"; // check that the user was healthy before all callbacks. We can only assert this after we included all the needed axioms. assert healthyOrLockedBeforeCallbacks, "user is healthy or locked before callbacks"; @@ -315,7 +287,7 @@ rule stayHealthyOrLocked(env e, method f, calldataarg args) filtered { f -> f.se // This variable is set to false whenever isHealthy() is violated before a callback. Initially we set it to true to indicate no violations detected. healthyOrLockedBeforeCallbacks = true; - require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomDownMonotoneA(a1, a2, b, d), "axiom"; + require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomMathMulDivDownMonotoneA(a1, a2, b, d), "axiom"; Midnight.Market globalMarket = getGlobalMarket(); diff --git a/certora/specs/MulDiv.spec b/certora/specs/MulDiv.spec index 2c3b2e783..946a794b1 100644 --- a/certora/specs/MulDiv.spec +++ b/certora/specs/MulDiv.spec @@ -160,6 +160,11 @@ rule mathMulDivMonotoneD(mathint a, mathint b, mathint d1, mathint d2) { assert a >= 0 && b >= 0 && 0 < d1 && d1 <= d2 => mathMulDivUp(a, b, d1) >= mathMulDivUp(a, b, d2); } +rule mathMulDivMonotoneBD(mathint a, mathint b1, mathint b2, mathint d1, mathint d2) { + assert a >= 0 && b1 >= 0 && b2 >= 0 && d1 > 0 && d2 > 0 && b1 * d2 <= d1 * b2 => mathMulDivDown(a, b1, d1) <= mathMulDivDown(a, b2, d2); + assert a >= 0 && b1 >= 0 && b2 >= 0 && d1 > 0 && d2 > 0 && b1 * d2 <= d1 * b2 => mathMulDivUp(a, b1, d1) <= mathMulDivUp(a, b2, d2); +} + // 1-Lipschitz in the first argument when b <= d: the result cannot grow faster than the numerator a. rule mathMulDivLipschitzA(mathint a1, mathint a2, mathint b, mathint d) { assert a1 >= 0 && b >= 0 && b <= d && a1 <= a2 => mathMulDivDown(a2, b, d) - mathMulDivDown(a1, b, d) <= a2 - a1; diff --git a/certora/specs/MulDivAxioms.spec b/certora/specs/MulDivAxioms.spec new file mode 100644 index 000000000..104c7b12c --- /dev/null +++ b/certora/specs/MulDivAxioms.spec @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association + +ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; + +ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; + +definition mathMulDivDown(mathint a, mathint b, mathint d) returns mathint = ghostMulDivDown(a, b, d); + +definition mathMulDivUp(mathint a, mathint b, mathint d) returns mathint = ghostMulDivUp(a, b, d); + +/* these are the axioms proved in MulDiv.spec */ + +definition axiomMathMulDivDownZeroA(mathint b, mathint d) returns bool = d > 0 => mathMulDivDown(0, b, d) == 0; + +definition axiomMathMulDivUpZeroA(mathint b, mathint d) returns bool = d > 0 => mathMulDivUp(0, b, d) == 0; + +definition axiomMathMulDivDownZeroB(mathint a, mathint d) returns bool = d > 0 => mathMulDivDown(a, 0, d) == 0; + +definition axiomMathMulDivUpZeroB(mathint a, mathint d) returns bool = d > 0 => mathMulDivUp(a, 0, d) == 0; + +definition axiomMathMulDivDownMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && b >= 0 && d >= 0 && a1 <= a2 => mathMulDivDown(a1, b, d) <= mathMulDivDown(a2, b, d); + +definition axiomMathMulDivUpMonotoneA(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && b >= 0 && d >= 0 && a1 <= a2 => mathMulDivUp(a1, b, d) <= mathMulDivUp(a2, b, d); + +definition axiomMathMulDivDownMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = a >= 0 && b1 >= 0 && d >= 0 && b1 <= b2 => mathMulDivDown(a, b1, d) <= mathMulDivDown(a, b2, d); + +definition axiomMathMulDivUpMonotoneB(mathint a, mathint b1, mathint b2, mathint d) returns bool = a >= 0 && b1 >= 0 && d >= 0 && b1 <= b2 => mathMulDivUp(a, b1, d) <= mathMulDivUp(a, b2, d); + +definition axiomMathMulDivDownMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = a >= 0 && b >= 0 && 0 < d1 && d1 <= d2 => mathMulDivDown(a, b, d1) >= mathMulDivDown(a, b, d2); + +definition axiomMathMulDivUpMonotoneD(mathint a, mathint b, mathint d1, mathint d2) returns bool = a >= 0 && b >= 0 && 0 < d1 && d1 <= d2 => mathMulDivUp(a, b, d1) >= mathMulDivUp(a, b, d2); + +definition axiomMathMulDivDownMonotoneBD(mathint a, mathint b1, mathint b2, mathint d1, mathint d2) returns bool = a >= 0 && b1 >= 0 && b2 >= 0 && d1 > 0 && d2 > 0 && b1 * d2 <= d1 * b2 => mathMulDivDown(a, b1, d1) <= mathMulDivDown(a, b2, d2); + +definition axiomMathMulDivUpMonotoneBD(mathint a, mathint b1, mathint b2, mathint d1, mathint d2) returns bool = a >= 0 && b1 >= 0 && b2 >= 0 && d1 > 0 && d2 > 0 && b1 * d2 <= d1 * b2 => mathMulDivUp(a, b1, d1) <= mathMulDivUp(a, b2, d2); + +// 1-Lipschitz in the first argument when b <= d: the result cannot grow faster than the numerator a. +definition axiomMathMulDivDownLipschitzA(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && b >= 0 && b <= d && a1 <= a2 => mathMulDivDown(a2, b, d) - mathMulDivDown(a1, b, d) <= a2 - a1; + +definition axiomMathMulDivUpLipschitzA(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && b >= 0 && b <= d && a1 <= a2 => mathMulDivUp(a2, b, d) - mathMulDivUp(a1, b, d) <= a2 - a1; + +// 1-Lipschitz in the second argument when a <= d: the result cannot grow faster than the numerator b. +definition axiomMathMulDivDownLipschitzB(mathint a, mathint b1, mathint b2, mathint d) returns bool = a >= 0 && b1 >= 0 && a <= d && b1 <= b2 => mathMulDivDown(a, b2, d) - mathMulDivDown(a, b1, d) <= b2 - b1; + +definition axiomMathMulDivUpLipschitzB(mathint a, mathint b1, mathint b2, mathint d) returns bool = a >= 0 && b1 >= 0 && a <= d && b1 <= b2 => mathMulDivUp(a, b2, d) - mathMulDivUp(a, b1, d) <= b2 - b1; + +definition axiomMathMulDivAddDownDown(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => mathMulDivDown(a1, b, d) + mathMulDivDown(a2, b, d) <= mathMulDivDown(a1 + a2, b, d); + +// Sub-additivity upper bound for mathMulDivDown: floor((a1+a2)*b/d) <= floor(a1*b/d) + floor(a2*b/d) + 1. +definition axiomMathMulDivAddDownDownTight(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 => mathMulDivDown(a1 + a2, b, d) <= mathMulDivDown(a1, b, d) + mathMulDivDown(a2, b, d) + 1; + +// Super-additivity upper bound for mathMulDivUp: ceil((a1+a2)*b/d) <= ceil(a1*b/d) + ceil(a2*b/d). +definition axiomMathMulDivAddUpUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 => mathMulDivUp(a1 + a2, b, d) <= mathMulDivUp(a1, b, d) + mathMulDivUp(a2, b, d); + +// Super-additivity lower bound for mathMulDivUp: ceil(a1*b/d) + ceil(a2*b/d) <= ceil((a1+a2)*b/d) + 1. +definition axiomMathMulDivAddUpUpTight(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 && b >= 0 && d > 0 => mathMulDivUp(a1, b, d) + mathMulDivUp(a2, b, d) <= mathMulDivUp(a1 + a2, b, d) + 1; + +definition axiomMathMulDivAddDownUp(mathint a1, mathint a2, mathint b, mathint d) returns bool = a1 >= 0 && a2 >= 0 => mathMulDivDown(a1, b, d) + mathMulDivUp(a2, b, d) >= mathMulDivDown(a1 + a2, b, d); + +definition axiomMathMulDivInverseDownUp(mathint a, mathint b, mathint d) returns bool = b > 0 && d > 0 => a <= mathMulDivDown(mathMulDivUp(a, b, d), d, b); + +definition axiomMathMulDivInverseUpDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && d > 0 => mathMulDivUp(mathMulDivDown(a, b, d), d, b) <= a; + +definition axiomMathMulDivDownArgumentLesserThanDenominatorA(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && a <= d => mathMulDivDown(a, b, d) <= b; + +definition axiomMathMulDivUpArgumentLesserThanDenominatorA(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && a <= d => mathMulDivUp(a, b, d) <= b; + +definition axiomMathMulDivDownArgumentLesserThanDenominatorB(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && b <= d => mathMulDivDown(a, b, d) <= a; + +definition axiomMathMulDivUpArgumentLesserThanDenominatorB(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && b <= d => mathMulDivUp(a, b, d) <= a; + +// Identity (b = d = x): floor(a*x/x) = ceil(a*x/x) = a. +definition axiomMathMulDivDownIdentity(mathint a, mathint x) returns bool = a >= 0 && x > 0 => mathMulDivDown(a, x, x) == a; + +definition axiomMathMulDivUpIdentity(mathint a, mathint x) returns bool = a >= 0 && x > 0 => mathMulDivUp(a, x, x) == a; + +definition axiomMathMulDivDownRoundsDown(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 => mathMulDivDown(a, b, d) * d <= a * b; + +definition axiomMathMulDivDownTightBound(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && d > 0 => (mathMulDivDown(a, b, d) + 1) * d > a * b; + +definition axiomMathMulDivUpRoundsUp(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && d > 0 => mathMulDivUp(a, b, d) * d >= a * b; + +definition axiomMathMulDivUpGeqMulDivDown(mathint a, mathint b, mathint d) returns bool = mathMulDivUp(a, b, d) >= mathMulDivDown(a, b, d); + +definition axiomMathMulDivUpTightBound(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && d > 0 && mathMulDivUp(a, b, d) > 0 => (mathMulDivUp(a, b, d) - 1) * d < a * b; + +definition axiomMathMulDivUpUpperBound(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && d > 0 => mathMulDivUp(a, b, d) * d <= a * b + d - 1; + +definition axiomMathMulDivDownResidualBound(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && a <= d && b <= d => a - mathMulDivDown(a, b, d) <= d - b; + +definition axiomMathMulDivUpResidualBound(mathint a, mathint b, mathint d) returns bool = a >= 0 && b >= 0 && a <= d && b <= d => a - mathMulDivUp(a, b, d) <= d - b; diff --git a/certora/specs/TakeAmountsLibInvertibility.spec b/certora/specs/TakeAmountsLibInvertibility.spec index 5bf3da3df..9c0dcebd0 100644 --- a/certora/specs/TakeAmountsLibInvertibility.spec +++ b/certora/specs/TakeAmountsLibInvertibility.spec @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association +import "MulDivAxioms.spec"; + using Utils as Utils; using TakeAmountsLibHarness as TakeAmountsLibHarness; @@ -45,29 +47,15 @@ persistent ghost summaryTickToPrice(uint256) returns uint256 { definition WAD() returns uint256 = 10 ^ 18; -/// MULDIV GHOST SUMMARIES (mirrors AccrualRounding.spec) /// - -// MulDiv rounding axioms (each proved in MulDiv.spec); inlined on ghosts instead of requireMulDivAxioms(). -persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint { - // proved in mulDivUpRoundsUp - axiom forall uint256 b. forall uint256 d. d > 0 => ghostMulDivDown(0, b, d) == 0; - - // proved in mulDivDownRoundsDown - axiom forall mathint a. forall mathint b. forall mathint d. 0 <= a && 0 <= b && 0 < d => ghostMulDivDown(a, b, d) * d <= a * b; +// MulDiv rounding axioms +function mathMulDivAxioms() { + require forall mathint b. forall mathint d. axiomMathMulDivDownZeroA(b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomMathMulDivDownRoundsDown(a, b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomMathMulDivDownTightBound(a, b, d), "axiom"; - // proved in mulDivDownTightBound - axiom forall mathint a. forall mathint b. forall mathint d. 0 <= a && 0 <= b && 0 < d => (ghostMulDivDown(a, b, d) + 1) * d > a * b; -} - -persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint { - // proved in mulDivUpRoundsUp - axiom forall uint256 b. forall uint256 d. d > 0 => ghostMulDivUp(0, b, d) == 0; - - // proved in mulDivUpRoundsUp - axiom forall mathint a. forall mathint b. forall mathint d. 0 <= a && 0 <= b && 0 < d => ghostMulDivUp(a, b, d) * d >= a * b; - - // proved in mulDivUpUpperBound - axiom forall mathint a. forall mathint b. forall mathint d. 0 <= a && 0 <= b && 0 < d => ghostMulDivUp(a, b, d) * d <= a * b + d - 1; + require forall mathint b. forall mathint d. axiomMathMulDivUpZeroA(b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomMathMulDivUpRoundsUp(a, b, d), "axiom"; + require forall mathint a. forall mathint b. forall mathint d. axiomMathMulDivUpTightBound(a, b, d), "axiom"; } function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { @@ -90,6 +78,8 @@ function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { // // If buyerAssetsToUnits(midnight, id, offer, T) returns u, then take(u, ...) produces buyerAssets == T. rule buyerAssetsReachable(env e, Midnight.Offer offer, uint256 targetBuyerAssets, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, bytes ratifierData) { + mathMulDivAxioms(); + bytes32 id = summaryToId(offer.market); uint256 units = TakeAmountsLibHarness.buyerAssetsToUnits(e, currentContract, id, offer, targetBuyerAssets); @@ -105,6 +95,8 @@ rule buyerAssetsReachable(env e, Midnight.Offer offer, uint256 targetBuyerAssets // // If sellerAssetsToUnits(midnight, id, offer, T) returns u, then take(u, ...) produces sellerAssets == T. rule sellerAssetsReachable(env e, Midnight.Offer offer, uint256 targetSellerAssets, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, bytes ratifierData) { + mathMulDivAxioms(); + bytes32 id = summaryToId(offer.market); uint256 units = TakeAmountsLibHarness.sellerAssetsToUnits(e, currentContract, id, offer, targetSellerAssets); From 42ad5123facec1a91f0b761cbd0f95a0f7b64494 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 6 Aug 2026 18:07:27 +0200 Subject: [PATCH 136/159] fix assertion --- certora/specs/TakeAmountsLibInvertibility.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/TakeAmountsLibInvertibility.spec b/certora/specs/TakeAmountsLibInvertibility.spec index 9c0dcebd0..e097ef117 100644 --- a/certora/specs/TakeAmountsLibInvertibility.spec +++ b/certora/specs/TakeAmountsLibInvertibility.spec @@ -62,14 +62,14 @@ function summaryMulDivDown(uint256 a, uint256 b, uint256 d) returns uint256 { if (d == 0 || a * b >= 2 ^ 256) { revert(); } - return assert_uint256(ghostMulDivDown(a, b, d)); + return require_uint256(ghostMulDivDown(a, b, d)); } function summaryMulDivUp(uint256 a, uint256 b, uint256 d) returns uint256 { if (d == 0 || a * b + d - 1 >= 2 ^ 256) { revert(); } - return assert_uint256(ghostMulDivUp(a, b, d)); + return require_uint256(ghostMulDivUp(a, b, d)); } /// TAKE AMOUNTS LIB INVERTIBILITY /// From 29b71a349b841aca2ec231ea96fc3e8c1976668a Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 13 Aug 2026 13:26:53 +0200 Subject: [PATCH 137/159] Make ghost persistent (they never change) --- certora/specs/MulDivAxioms.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certora/specs/MulDivAxioms.spec b/certora/specs/MulDivAxioms.spec index 104c7b12c..659a29e1a 100644 --- a/certora/specs/MulDivAxioms.spec +++ b/certora/specs/MulDivAxioms.spec @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; +persistent ghost ghostMulDivDown(mathint, mathint, mathint) returns mathint; -ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; +persistent ghost ghostMulDivUp(mathint, mathint, mathint) returns mathint; definition mathMulDivDown(mathint a, mathint b, mathint d) returns mathint = ghostMulDivDown(a, b, d); From e113fc0f375cc02f77f7d341c037b4fe2da90ee2 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 13:58:55 +0000 Subject: [PATCH 138/159] [blue fallback rolling] require non-decreasing incentive Drop the decreasing branch of the incentive ramp in `roll` and require `incentiveAtEnd >= incentiveAtStart` in `setConfig`, so the incentive can only increase over the rolling window. --- src/periphery/README.md | 2 +- .../BlueFallbackRolling.sol | 8 ++- .../interfaces/IBlueFallbackRolling.sol | 1 + test/BlueFallbackRollingTest.sol | 53 ++++++------------- 4 files changed, 20 insertions(+), 44 deletions(-) diff --git a/src/periphery/README.md b/src/periphery/README.md index 982ace094..2af7e35d0 100644 --- a/src/periphery/README.md +++ b/src/periphery/README.md @@ -29,7 +29,7 @@ It supplies the activated collateral to Blue before, through a callback, borrowi Users and accounts they authorize on Midnight may enable multiple fallback configurations per Midnight market. Users must authorize the contract on both Midnight and Blue. Each configuration selects a Blue market, a Midnight market, start timestamp, end timestamp, caller incentive at start, caller incentive at end, and minimum rollable amount, and can later be disabled. -The caller incentive is a percentage of the debt, is capped at 100% and evolves linearly between start and end. +The caller incentive is a percentage of the debt, is capped at 100% and increases linearly between start and end. The minimum rollable amount is the smallest debt a single roll can migrate, and is bypassed by a roll migrating the whole remaining Midnight debt, so a position can always be closed out. A roll requires the borrower to have exactly one activated Midnight collateral, matching the collateral token of the configured Blue market. diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index bc41be5cd..81a7e8fc7 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -47,6 +47,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { require(start < end, EndNotAfterStart()); require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); + require(incentiveAtEnd >= incentiveAtStart, DecreasingIncentive()); bytes32 configId = keccak256(abi.encode(midnightId, blueId, start, end, incentiveAtStart, incentiveAtEnd, minRollableAssets)); @@ -101,11 +102,8 @@ contract BlueFallbackRolling is IBlueFallbackRolling { uint256 collateralAssets = IMidnight(MIDNIGHT).collateral(midnightId, user, collateralIndex).mulDivDown(assets, debtAssets); // Round against the roller. - uint256 incentiveFactor = incentiveAtEnd >= incentiveAtStart - ? incentiveAtStart - + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start) - : incentiveAtStart - - UtilsLib.mulDivUp(incentiveAtStart - incentiveAtEnd, block.timestamp - start, end - start); + uint256 incentiveFactor = incentiveAtStart + + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 673380f53..491ca51b4 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -8,6 +8,7 @@ import {Market} from "../../../interfaces/IMidnight.sol"; interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { /// ERRORS /// + error DecreasingIncentive(); error Ended(); error EndNotAfterStart(); error IncentiveTooHigh(); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index fb8012eac..e9ad712c3 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -235,44 +235,6 @@ contract BlueFallbackRollingTest is BaseTest { assertEq(midnight.debt(toId(midnightMarket), borrower), 0); } - function testRollPaysTheAuctionedIncentiveWhenDecreasing(uint256 elapsed) public { - elapsed = bound(elapsed, 0, end - start); - vm.prank(borrower); - fallbackContract.setConfig( - borrower, - toId(midnightMarket), - Id.unwrap(blueMarketParams.id()), - start, - end, - INCENTIVE_AT_END, - INCENTIVE_AT_START, - MIN_ROLLABLE_ASSETS, - true - ); - vm.warp(start + elapsed); - - vm.prank(keeper); - fallbackContract.roll( - midnightMarket, - blueMarketParams, - borrower, - start, - end, - INCENTIVE_AT_END, - INCENTIVE_AT_START, - MIN_ROLLABLE_ASSETS, - DEBT - ); - - uint256 duration = end - start; - uint256 decrease = (INCENTIVE_AT_END - INCENTIVE_AT_START) * elapsed; - - uint256 expected = INCENTIVE_AT_END - (decrease + duration - 1) / duration; - assertEq(loanToken.balanceOf(keeper), DEBT * expected / WAD); - assertEq(loanToken.balanceOf(address(fallbackContract)), 0); - assertEq(midnight.debt(toId(midnightMarket), borrower), 0); - } - function testRollPaysTheAuctionedIncentiveWhenTheAuctionEndsAfterMaturity() public { uint64 lateEnd = uint64(midnightMarket.maturity) + 1 days; vm.prank(borrower); @@ -533,6 +495,21 @@ contract BlueFallbackRollingTest is BaseTest { ); } + function testSetConfigRevertsForDecreasingIncentive() public { + vm.expectRevert(IBlueFallbackRolling.DecreasingIncentive.selector); + fallbackContract.setConfig( + address(this), + toId(midnightMarket), + Id.unwrap(blueMarketParams.id()), + start, + end, + INCENTIVE_AT_END, + INCENTIVE_AT_START, + MIN_ROLLABLE_ASSETS, + true + ); + } + function testSetConfigRevertsForEndBeforeStart() public { vm.expectRevert(IBlueFallbackRolling.EndNotAfterStart.selector); fallbackContract.setConfig( From 5277f605d868cad46da1cb82ed43ea3e36b5339d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 14:11:29 +0000 Subject: [PATCH 139/159] [blue fallback rolling] remove redundant incentive check --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 1 - test/BlueFallbackRollingTest.sol | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 81a7e8fc7..85b5a245f 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -45,7 +45,6 @@ contract BlueFallbackRolling is IBlueFallbackRolling { ) external override { require(msg.sender == user || IMidnight(MIDNIGHT).isAuthorized(user, msg.sender), Unauthorized()); require(start < end, EndNotAfterStart()); - require(incentiveAtStart <= WAD, IncentiveTooHigh()); require(incentiveAtEnd <= WAD, IncentiveTooHigh()); require(incentiveAtEnd >= incentiveAtStart, DecreasingIncentive()); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index e9ad712c3..e8ef17335 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -489,7 +489,7 @@ contract BlueFallbackRollingTest is BaseTest { start, end, incentiveAtStart, - MAX_INCENTIVE, + incentiveAtStart, MIN_ROLLABLE_ASSETS, true ); From 56f27bf9d8aa107cab38587d88ccdc7e594af8cc Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 10:53:52 +0000 Subject: [PATCH 140/159] [blue fallback rolling] add configId to Roll event --- src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol | 2 +- .../blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol | 2 +- test/BlueFallbackRollingTest.sol | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol index 85b5a245f..54525ca77 100644 --- a/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/BlueFallbackRolling.sol @@ -105,7 +105,7 @@ contract BlueFallbackRolling is IBlueFallbackRolling { + UtilsLib.mulDivDown(incentiveAtEnd - incentiveAtStart, block.timestamp - start, end - start); uint256 incentiveAssets = UtilsLib.mulDivDown(assets, incentiveFactor, WAD); - emit Roll(msg.sender, user, midnightId, blueId, assets, collateralAssets, incentiveAssets); + emit Roll(msg.sender, user, midnightId, blueId, configId, assets, collateralAssets, incentiveAssets); bytes memory data = abi.encode(midnightMarket, blueMarketParams, collateralIndex, assets, incentiveAssets, user); IMorpho(BLUE).supplyCollateral(blueMarketParams, collateralAssets, user, data); diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 491ca51b4..3cae2f46f 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -24,7 +24,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { // forgefmt: disable-start /// EVENTS /// event SetConfig(address caller, address indexed user, bytes32 indexed midnightId, bytes32 indexed blueId, uint256 start, uint256 end, uint256 incentiveAtStart, uint256 incentiveAtEnd, uint256 minRollableAssets, bool enabled); - event Roll(address indexed caller, address indexed user, bytes32 indexed midnightId, bytes32 blueId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets); + event Roll(address indexed caller, address indexed user, bytes32 indexed midnightId, bytes32 blueId, bytes32 configId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets); /// STORAGE GETTERS /// function MIDNIGHT() external view returns (address); diff --git a/test/BlueFallbackRollingTest.sol b/test/BlueFallbackRollingTest.sol index e8ef17335..9afec0842 100644 --- a/test/BlueFallbackRollingTest.sol +++ b/test/BlueFallbackRollingTest.sol @@ -730,6 +730,7 @@ contract BlueFallbackRollingTest is BaseTest { borrower, toId(midnightMarket), Id.unwrap(blueMarketParams.id()), + configId(start, end, INCENTIVE_AT_START, INCENTIVE_AT_END, MIN_ROLLABLE_ASSETS), DEBT, collateralAssets, DEBT * INCENTIVE_AT_END / WAD From 7f9a1e1192b9d0ef7a6bee47b8f152919e32d295 Mon Sep 17 00:00:00 2001 From: PA <50184410+peyha@users.noreply.github.com> Date: Fri, 21 Aug 2026 10:24:53 +0200 Subject: [PATCH 141/159] Apply suggestion from @peyha Signed-off-by: PA <50184410+peyha@users.noreply.github.com> --- .../blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol index 3cae2f46f..cbe6362cb 100644 --- a/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol +++ b/src/periphery/blue-fallback-rolling/interfaces/IBlueFallbackRolling.sol @@ -24,7 +24,7 @@ interface IBlueFallbackRolling is IMorphoSupplyCollateralCallback { // forgefmt: disable-start /// EVENTS /// event SetConfig(address caller, address indexed user, bytes32 indexed midnightId, bytes32 indexed blueId, uint256 start, uint256 end, uint256 incentiveAtStart, uint256 incentiveAtEnd, uint256 minRollableAssets, bool enabled); - event Roll(address indexed caller, address indexed user, bytes32 indexed midnightId, bytes32 blueId, bytes32 configId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets); + event Roll(address caller, address indexed user, bytes32 indexed midnightId, bytes32 indexed blueId, bytes32 configId, uint256 debtAssets, uint256 collateralAssets, uint256 incentiveAssets); /// STORAGE GETTERS /// function MIDNIGHT() external view returns (address); From 34b1ce04a63f4ef9d8c8d6c298492335d998bd64 Mon Sep 17 00:00:00 2001 From: "prd-carapulse[bot]" <264278285+prd-carapulse[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:58:36 +0000 Subject: [PATCH 142/159] ci: pin foundry-toolchain to v1.9.1 Pins foundry-rs/foundry-toolchain to the v1.9.1 commit 908c540300062bd5a7e473851cdb4282204cee09.\n\nWhy now: foundryup became a Rust binary in foundry-rs/foundry#15498, while the v1.7 bootstrap program still invokes it as a bash script. The bootstrap fetches the latest foundryup, so the unpinned action can now break CI.\n\nVerification: workflow and local composite-action files containing foundry-rs/foundry-toolchain were updated; tests not run (workflow ref update only).\n\nRequested by: <@U03C031MDG8> | Quentin Garchery --- .github/workflows/forge-old.yml | 4 ++-- .github/workflows/forge.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/forge-old.yml b/.github/workflows/forge-old.yml index e97928343..38d4ee827 100644 --- a/.github/workflows/forge-old.yml +++ b/.github/workflows/forge-old.yml @@ -16,7 +16,7 @@ jobs: with: submodules: recursive - name: Install Foundry (old) - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 with: version: v1.5.1 - name: Verify forge executable hash @@ -49,7 +49,7 @@ jobs: - name: Run Forge tests run: forge test - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 - name: Build with Foundry run: forge build --force --out out-new --cache-path cache-new - name: Export bytecode manifest (new) diff --git a/.github/workflows/forge.yml b/.github/workflows/forge.yml index 40723fabd..f061fc71a 100644 --- a/.github/workflows/forge.yml +++ b/.github/workflows/forge.yml @@ -17,7 +17,7 @@ jobs: submodules: recursive - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 - name: Check formatting run: forge fmt src test script certora --check @@ -30,7 +30,7 @@ jobs: submodules: recursive - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 - name: Run forge lint run: forge lint src test script certora --deny notes @@ -43,7 +43,7 @@ jobs: submodules: recursive - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 - name: Run forge build run: forge build --force --sizes @@ -70,7 +70,7 @@ jobs: with: submodules: recursive - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1 + uses: foundry-rs/foundry-toolchain@908c540300062bd5a7e473851cdb4282204cee09 # v1.9.1 - name: Run Forge tests (${{ matrix.name }}) run: forge test --deny warnings env: From 008b787b61ee120cb8333fcdb098c06e5e239917 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 31 Aug 2026 21:33:01 +0200 Subject: [PATCH 143/159] reduced scope to soundness and reference implementation generating roo --- certora/README.md | 33 --- certora/checker/Checker.sol | 62 ---- certora/checker/OfferVerificationToolChain.md | 229 --------------- certora/checker/create_certificate.py | 270 ------------------ certora/confs/OfferTreeMembership.conf | 6 +- certora/confs/Ratification.conf | 1 + certora/helpers/OfferTree.sol | 51 +++- certora/helpers/Utils.sol | 19 +- certora/specs/OfferTreeMembership.spec | 25 +- certora/specs/OfferTreeWellFormed.spec | 1 + certora/specs/Ratification.spec | 6 +- foundry.toml | 5 - 12 files changed, 69 insertions(+), 639 deletions(-) delete mode 100644 certora/checker/Checker.sol delete mode 100644 certora/checker/OfferVerificationToolChain.md delete mode 100644 certora/checker/create_certificate.py diff --git a/certora/README.md b/certora/README.md index 94f534f19..5680c7947 100644 --- a/certora/README.md +++ b/certora/README.md @@ -56,39 +56,6 @@ How offers are consumed when taken. - [`SplitPreservesAccounting.spec`](specs/SplitPreservesAccounting.spec) checks that taking `A` units at once leaves the same credit, debt, total units, loss factors, accrual timestamps and continuous fee credit as taking `B` then `C`, with `A = B + C`. - [`SplitDoesNotPunishMakerOrFavorTaker.spec`](specs/SplitDoesNotPunishMakerOrFavorTaker.spec) checks the asset side of that split: splitting a take never makes the maker pay more or receive less, nor the taker pay less or receive more, up to one wei of rounding. -## Offer trees - -Offers are authorized in batches: a ratifier signs a single Merkle root over an offer tree, and a `take` only succeeds if the offer's hash is proven to be a leaf under that root. -Objective is to show that a successful `take` can only settle an offer that was genuinely committed in the signed tree. -We reason about [`OfferTree`](helpers/OfferTree.sol), a model of the tree built only through the `newLeaf` and `newInternalNode` primitives. Leaves are keyed by `HashLib.hashOffer(offer)` and store a fixed-size pre-image of the offer, so `isWellFormed` re-hashes a leaf with a single bounded keccak instead of looping over the offer's dynamic members, which keeps the proofs bounded regardless of offer size. - -- [`OfferTreeWellFormed.spec`](specs/OfferTreeWellFormed.spec) checks that the primitives only ever build well-formed trees: every node is empty, a leaf carrying a genuine `hashOffer`, or an internal node correctly hashing its two children. In particular, there is no restriction for the left and right children of a parent node to be sorted. -- [`OfferTreeMembership.spec`](specs/OfferTreeMembership.spec) checks the main soundness result: for any well-formed tree, if a Merkle proof verifies an offer's hash against the root, then the offer is registered as a leaf. Equivalently, no valid proof can be forged for an offer that is not in the tree. -- [`Ratification.spec`](specs/Ratification.spec) connects this to the on-chain path: every successful `isRatified` (across all ratifier implementations) and every successful `take` actually invokes `HashLib.isLeaf` and it returns true. - -Combining the three: a successful `take` runs a Merkle membership check against the ratified root (`Ratification`), which for a well-formed root implies the offer is genuinely a leaf of that tree (`OfferTreeMembership`), and the root is well-formed because it is built only from the well-formedness-preserving primitives (`OfferTreeWellFormed`). - -### Checking a concrete root - -The membership result is stated for any well-formed root; the checker in [`checker`](checker) lets anyone confirm what a specific root commits to, by rebuilding the tree through the same verified primitives. - -1. Write a `proofs.json` listing the claimed `root` and the offers (`leaves`), padded to a power of two with empty offers. -2. Generate the certificate, from the repository root: - ``` - python certora/checker/create_certificate.py proofs.json - ``` - This recomputes the tree bottom-up, asserts the computed root equals the claimed `root`, and writes `certificate.json`. -3. Replay it through the verified primitives: - ``` - FOUNDRY_PROFILE=checker forge test --match-test testVerifyCertificate - ``` - [`Checker.sol`](checker/Checker.sol) reads `certificate.json`, rebuilds the tree via `OfferTree.newLeaf`/`newInternalNode`, and asserts the constructed root equals `root`. - -A passing run certifies that the root is the root of a well-formed tree built from exactly those offers, so the membership guarantee applies to it. -This confirms what a root commits to, not that it was signed; verifying the ratifier's signature is a separate step. - -The verification setup and technique is inspired from the Merkle Tree Membership soundness spec in [Universal Rewards Distributor](https://github.com/morpho-org/universal-rewards-distributor/). - ## Fees Continuous-fee accrual and settlement-fee rounding stay within their expected bounds. diff --git a/certora/checker/Checker.sol b/certora/checker/Checker.sol deleted file mode 100644 index 540308c9f..000000000 --- a/certora/checker/Checker.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -// Copyright (c) 2025 Morpho Association -pragma solidity ^0.8.0; - -import {Test} from "../../lib/forge-std/src/Test.sol"; -import {stdJson} from "../../lib/forge-std/src/StdJson.sol"; - -import {OfferTree} from "../helpers/OfferTree.sol"; -import {Offer} from "../../src/interfaces/IMidnight.sol"; -import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; - -contract Checker is Test { - using stdJson for string; - - struct InternalNode { - bytes32 id; - bytes32 left; - bytes32 right; - } - - // Replay the certificate through the verified `newLeaf` and `newInternalNode` - // primitives, then assert that the final certificate item matches `root`. - function testVerifyCertificate() public { - string memory path = string.concat(vm.projectRoot(), "/certificate.json"); - if (!vm.exists(path)) vm.skip(true, "no certificate.json at project root"); - - string memory json = vm.readFile(path); - bytes32 root = json.readBytes32(".root"); - - uint256 leafLength = json.readUint(".leafLength"); - Offer[] memory leaves = new Offer[](leafLength); - for (uint256 i = 0; i < leafLength; i++) { - bytes memory enc = json.readBytes(string.concat(".leaf[", vm.toString(i), "]")); - leaves[i] = abi.decode(enc, (Offer)); - } - - uint256 nodeLength = json.readUint(".nodeLength"); - InternalNode[] memory nodes = new InternalNode[](nodeLength); - for (uint256 i = 0; i < nodeLength; i++) { - bytes memory enc = json.readBytes(string.concat(".node[", vm.toString(i), "]")); - nodes[i] = abi.decode(enc, (InternalNode)); - } - - require(leaves.length > 0, "no leaves"); - require(nodes.length > 0 || leaves.length == 1, "missing internal nodes"); - - OfferTree tree = new OfferTree(); - - for (uint256 i = 0; i < leaves.length; i++) { - tree.newLeaf(leaves[i]); - } - - bytes32 rootId = HashLib.hashOffer(leaves[0]); - for (uint256 i = 0; i < nodes.length; i++) { - InternalNode memory node = nodes[i]; - tree.newInternalNode(node.id, node.left, node.right); - rootId = node.id; - } - - assertEq(tree.getHash(rootId), root, "mismatched roots"); - } -} diff --git a/certora/checker/OfferVerificationToolChain.md b/certora/checker/OfferVerificationToolChain.md deleted file mode 100644 index dd60d474c..000000000 --- a/certora/checker/OfferVerificationToolChain.md +++ /dev/null @@ -1,229 +0,0 @@ -# The Offer Verification Toolchain - -How a maker can know — without trusting the front end, the SDK, their wallet software, or -their hardware wallet's EIP-712 parser — that the offer-tree root they approve commits to -exactly the offers they intend, and nothing else. - -## Why this exists: hardware wallets cannot clear-sign the tree - -Makers originally clear-signed the full EIP-712 `OfferTree`. Its Merkle representation is -a deeply nested array type (`Offer[2][2]…[2]`), and hardware-wallet firmware must parse -that structure on-device to clear-sign it. Much of the ecosystem cannot: - -- **Ledger** (Nano X / S Plus / Flex / Stax): the clear-sign path fails with `0x6a00` on - larger nested trees; older Ethereum apps (1.17–1.19.3) could produce an *incorrect - signature* due to a device-side hashing bug. -- **Trezor** (Model T / Safe 3/5/7): hard failure — firmware does not support - arrays-of-arrays. -- **Original Nano S**: blind signing works but displays nothing meaningful. -- **Custody platforms**: same failure class at different limits (a 64-leaf - `Offer[2][2][2][2][2][2]` exceeded one vendor's nesting cap of 10). -- **Software wallets** work only because the *host* computes the digest — which is - exactly the machine we don't want to have to trust. - -The failure is structural, not fixable by simplifying an offer field: a routine -single-market chain reaches 32 leaves (six array levels), and multi-market trees reach -256 leaves. Behavior also depends on wallet *software*, not just the device (the same -Ledger succeeded through one wallet's blind-sign path and failed through another's -clear-sign path), and a dapp can neither choose that path nor detect that an EIP-1193 -account is hardware-backed. - -**The decision shipped:** makers approve the tree *root* instead of signing the tree — -today via an on-chain [`SetterRatifier`](../../src/ratifiers/SetterRatifier.sol) -transaction (hardware-compatible, reversible, one cheap transaction per batch); longer -term via a root-only EIP-712 ratifier that restores off-chain signing without exposing -the nested type to device parsers. - -This fixes the device problem but creates a verification problem: **the root is an opaque -32 bytes**. The device can display it faithfully, but nothing on the device tells the -maker what it commits them to. The toolchain in this directory rebuilds that missing -"what am I approving?" verification as an independent, locally runnable pipeline. - -## The trust chain - -``` -offers JSON (human-reviewed intent) - │ create_certificate.py — independent Python implementation (eth_abi/web3) - ▼ -root + certificate.json (flat leaf/node instruction lists — no nested arrays anywhere) - │ Checker.sol — replays through the real HashLib via OfferTree.newLeaf/newInternalNode - ▼ -"the root matches under Solidity's own hashing" - │ Certora proofs — OfferTreeWellFormed.spec + OfferTreeMembership.spec - ▼ -"the root commits to EXACTLY these offers at settlement time" - │ device screen — compare 32 bytes - ▼ -root approval (SetterRatifier tx today; root-only EIP-712 signature later) -``` - -Each link removes one party from the trusted base. No single tool is trusted: the Python -and Solidity implementations share no code and must agree, and the formal proofs pin down -what their agreement *means*. - -## The maker's workflow, step by step - -### Step 0 — Formal verification of the primitives (per release, not per user) - -Run by CI: `certoraRun certora/confs/OfferTreeWellFormed.conf` and -`certora/confs/OfferTreeMembership.conf`. - -- [`OfferTreeWellFormed.spec`](../specs/OfferTreeWellFormed.spec) proves that any tree - built through `newLeaf`/`newInternalNode` is well-formed, that a stored leaf re-hashes - to the real `HashLib.hashOffer` (`hashLeafReproducesHashOffer`), and states the two - keccak-model axioms the whole chain rests on: leaf/internal-node domain separation - (`leafHashDisjointFromNodeHash`) and `hashNode` injectivity. -- [`OfferTreeMembership.spec`](../specs/OfferTreeMembership.spec) proves the headline - (`membershipSoundness`): an offer that passes on-chain `HashLib.isLeaf` against a - well-formed root **is a leaf of that tree**. - -**Guarantee:** a root is a binding commitment to exactly its leaf set — no hidden leaf, -no internal-node-as-leaf forgery, no offer with tweaked fields. -**Still open:** whether *your* root was computed from *your* offers. - -### Step 1 — Read the offers - -The front end / SDK produces `proofs.json`: the claimed root plus every offer in plain -fields (market, tick, expiry, `maxUnits`, `maxAssets`, `reduceOnly`, …). - -**Guarantee:** none — this is the intent step. Everything downstream proves the root -commits to *this file*, so this is the only thing the maker must actually read. - -### Step 2 — Independent root recomputation - -``` -python certora/checker/create_certificate.py proofs.json -``` - -Recomputes every hash bottom-up with an implementation -([`create_certificate.py`](create_certificate.py), built on `eth_abi`/`web3`) that shares -no code with the front end, and writes `certificate.json`. It hard-fails on root -mismatch, on leaf/node hash collisions, and — via `_check_typehashes`, which re-derives -the three EIP-712 typehashes from their type strings (mirroring -[`HashLibTest.sol`](../../test/HashLibTest.sol)) — on any typehash drift after a struct -change. - -**Guarantee:** the claimed root derives from the reviewed offers, independently of the -dapp, the SDK, wallet middleware, and device firmware. This removes exactly the failure -modes observed in the field: a divergent wallet signing path, a device hashing bug, a -tampered front end. -**Still open:** the Python mirror itself could mis-implement Solidity's hashing. - -### Step 3 — Canonical replay through Solidity - -``` -FOUNDRY_PROFILE=checker forge test --match-test testVerifyCertificate -``` - -[`Checker.sol`](Checker.sol) reads `certificate.json`, rebuilds the tree through -[`OfferTree.newLeaf`/`newInternalNode`](../helpers/OfferTree.sol) — which hash with the -**actual** [`HashLib`](../../src/ratifiers/libraries/HashLib.sol) Midnight executes at -settlement — and asserts the constructed root equals the claimed root. - -**Guarantee:** Python and Solidity cross-check each other, and one of them is the -canonical implementation. A bug in either makes the test fail; they cannot "agree -wrongly" unless two independent implementations share the same bug. -**Still open:** whether "these primitives reproduce the root" implies "the root commits -to exactly these offers" — which is precisely what Step 0 proved, over the very -primitives this replay uses. - -### Step 4 — Approve on the device - -Submit the root approval and compare the 32-byte root on the device screen against the -root printed in steps 2–3. - -- **Today:** `SetterRatifier.setIsRootRatified(maker, root, true)` — an ordinary - transaction, clear-signable on every device including Trezor and the original Nano S, - and *reversible* (set it back to `false` to unratify the whole batch). -- **Later:** a root-only EIP-712 signature — a flat struct with a single `bytes32`, no - nesting for any firmware to choke on. - -**Guarantee:** what the device displays is byte-for-byte the value the toolchain -verified. The device's inability to parse the tree no longer matters, because the tree -never reaches it. - -### Step 5 — Settlement - -Takers consume offers by presenting `(offer, leafIndex, proof)`; -[`SetterRatifier.isRatified`](../../src/ratifiers/SetterRatifier.sol) checks -`HashLib.isLeaf` against the approved root. - -**Guarantee (Step 0 + Steps 2–4 composed):** *the only offers that can ever settle under -this approval are exactly the ones in the file read in Step 1.* - -## The composed guarantee - -> If the 32 bytes on my device screen equal the root my local toolchain computed from -> offers I read, then my approval binds me to precisely those offers — nothing else. - -The front end, the SDK, the wallet software, and the device's EIP-712 parser are all -outside the trusted base. What remains: - -1. **The maker's own machine and toolchain** (Python deps, foundry, solc) — mitigable by - pinning/vendoring and running air-gapped. -2. **Keccak collision resistance** — stated explicitly as the `nodeHashInjective` / - `leafHashDisjointFromNodeHash` rules rather than assumed silently. -3. **Deployed bytecode = verified source** — the Certora proofs are about source; check - the deployed Midnight and ratifier addresses against it once (Etherscan/Sourcify). -4. **Semantic review** — the pipeline proves hash integrity, not that a tick or expiry is - sensible. Reading `proofs.json` in Step 1 is the one judgment step left in the flow. - -## Verifying a signature after the fact (EcrecoverRatifier path) - -For makers who *can* sign — note that -[`EcrecoverRatifier`](../../src/ratifiers/EcrecoverRatifier.sol) verifies a digest built -from the root alone: - -``` -structHash = keccak256(abi.encode(offerTreeTypeHash(height), root)) -domainSeparator = keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, chainId, ratifier)) -digest = keccak256("\x19\x01" ‖ domainSeparator ‖ structHash) -``` - -The nested `Offer[2][2]…` type exists only wallet-side: EIP-712's array hashing -(keccak of concatenated element hash-structs) recursively collapses to the Merkle root, -which is why `HashLib.hashNode` is exactly `keccak256(left ‖ right)`. - -A wallet never outputs a root, only `(v, r, s)` — so the after-the-fact check compares -*signers* instead of roots: recompute the root from the maker's own offers (steps 2–3), -rebuild the digest above from that recomputed root, and check -`ecrecover(digest, v, r, s)` equals the maker's address. A signature is valid for one -`(key, digest)` pair, and the digest is a collision-resistant function of the root — so -recovery yielding the maker's address is the cryptographic equivalent of "the signed root -equals the recomputed root". A front end that swapped offers changes the root, hence the -digest, and recovery yields some other address — never the maker's. (This check is not -currently implemented in `create_certificate.py`; the recipe above is what an -implementation must compute.) - -## If devices could clear-sign the tree, would this be redundant? - -Mostly — and seeing why sharpens what each piece is for. Correct clear signing fuses the -pipeline into one tamper-proof path: the trusted display is Step 1 (the digest is derived -on-device from the same bytes displayed, so host malware cannot decouple "what I read" -from "what gets hashed"), the device's firmware hashing is Step 2 (an independent -implementation isolated from the host), and EIP-712 conformance replaces Step 3 (device -and contract implement the same public standard, and `ecrecover` at settlement only -matches the maker if they agreed). There is no opaque root to compare, so Step 4's ritual -disappears too. - -Three things stay load-bearing regardless of signing method: - -1. **The contract-side proofs (Step 0).** `membershipSoundness` and domain separation - protect *settlement* against forged proofs — a taker re-presenting an internal 2-word - node hash as an "offer" — which has nothing to do with how the signature was made. -2. **Firmware as a single point of failure.** The Ledger 1.17–1.19.3 hashing bug is - exactly the failure this pipeline's two-independent-implementations design catches and - a device-only trust chain doesn't. The checker retains value as an audit layer. -3. **Review at scale.** Clear-signing 256 leaves × 15 fields on a device screen is - theoretical transparency but practical blind-signing-by-fatigue. A host-side JSON you - can read, diff, and script against is a better review surface for large trees. - -## Running it - -See the "checker" section of [`../README.md`](../README.md) for the two commands -(`create_certificate.py`, then `FOUNDRY_PROFILE=checker forge test`). - -## Internal references - -- Ledger investigation: MKT-1179 · SetterRatifier decision: MKT-1239 · custody nesting - cap: MKT-1552 (Linear, internal). diff --git a/certora/checker/create_certificate.py b/certora/checker/create_certificate.py deleted file mode 100644 index c3bdf5b98..000000000 --- a/certora/checker/create_certificate.py +++ /dev/null @@ -1,270 +0,0 @@ -import json -import sys - -from eth_abi import encode -from web3 import Web3 - -w3 = Web3() - -# Constants from src/ratifiers/libraries/HashLib.sol (checked against the type -# strings in test/HashLibTest.sol by _check_typehashes below). -COLLATERAL_PARAMS_TYPE = b"CollateralParams(address token,uint256 lltv,uint256 liquidationCursor,address oracle)" -MARKET_TYPE = b"Market(uint256 chainId,address midnight,address loanToken,CollateralParams[] collateralParams,uint256 maturity,uint256 rcfThreshold,address enterGate,address liquidatorGate)" -OFFER_TYPE = b"Offer(Market market,bool buy,address maker,uint256 start,uint256 expiry,uint256 tick,bytes32 group,address callback,bytes callbackData,address receiverIfMakerIsSeller,address ratifier,bool reduceOnly,uint128 maxUnits,uint128 maxAssets,uint256 continuousFeeCap)" - -COLLATERAL_PARAMS_TYPEHASH = bytes.fromhex( - "39ed3f928d24fd00574b1a02aba9c2483abcf5d9a3a366118c9a5aa29885b841" -) -MARKET_TYPEHASH = bytes.fromhex( - "510b3862f3816a109c9340b76972e8a30984246be06e034ae12ed2934220391a" -) -OFFER_TYPEHASH = bytes.fromhex( - "9905214264a9fb7b6cc1b0e33db7a04687c6e4185a84755d29914314aa9d8906" -) - -# ABI signature for `Offer` matching src/interfaces/IMidnight.sol field order. -OFFER_ABI_TYPE = ( - "(" - "(uint256,address,address,(address,uint256,uint256,address)[],uint256,uint256,address,address)," - "bool,address,uint256,uint256,uint256,bytes32,address,bytes,address,address,bool,uint128,uint128,uint256" - ")" -) -INTERNAL_NODE_ABI_TYPE = "(bytes32,bytes32,bytes32)" - - -# Safety checks use this instead of `assert`, which is stripped under `python -O`. -def _require(cond, msg): - if not cond: - raise ValueError(msg) - - -def _bytes32(v): - raw = bytes.fromhex(v.removeprefix("0x")) - _require(len(raw) == 32, f"expected 32 bytes, got {len(raw)}") - return raw - - -def _hexbytes(v): - return bytes.fromhex(v.removeprefix("0x")) - - -def _keccak_abi(types, values): - return w3.keccak(encode(types, values)) - - -# Pin the hardcoded typehashes to the EIP-712 type strings (mirrors test/HashLibTest.sol). -def _check_typehashes(): - _require( - w3.keccak(COLLATERAL_PARAMS_TYPE) == COLLATERAL_PARAMS_TYPEHASH, - "COLLATERAL_PARAMS_TYPEHASH does not match its type string", - ) - _require( - w3.keccak(MARKET_TYPE + COLLATERAL_PARAMS_TYPE) == MARKET_TYPEHASH, - "MARKET_TYPEHASH does not match its type string", - ) - _require( - w3.keccak(OFFER_TYPE + COLLATERAL_PARAMS_TYPE + MARKET_TYPE) == OFFER_TYPEHASH, - "OFFER_TYPEHASH does not match its type string", - ) - - -# Returns the abi-encoded form of an Offer, ready for `abi.decode(bytes, (Offer))`. -def abi_encode_offer(o): - m = o["market"] - market = ( - int(m["chainId"]), - w3.to_checksum_address(m["midnight"]), - w3.to_checksum_address(m["loanToken"]), - [ - ( - w3.to_checksum_address(cp["token"]), - int(cp["lltv"]), - int(cp["liquidationCursor"]), - w3.to_checksum_address(cp["oracle"]), - ) - for cp in m["collateralParams"] - ], - int(m["maturity"]), - int(m["rcfThreshold"]), - w3.to_checksum_address(m["enterGate"]), - w3.to_checksum_address(m["liquidatorGate"]), - ) - offer = ( - market, - bool(o["buy"]), - w3.to_checksum_address(o["maker"]), - int(o["start"]), - int(o["expiry"]), - int(o["tick"]), - _bytes32(o["group"]), - w3.to_checksum_address(o["callback"]), - _hexbytes(o["callbackData"]), - w3.to_checksum_address(o["receiverIfMakerIsSeller"]), - w3.to_checksum_address(o["ratifier"]), - bool(o["reduceOnly"]), - int(o["maxUnits"]), - int(o["maxAssets"]), - int(o["continuousFeeCap"]), - ) - return "0x" + encode([OFFER_ABI_TYPE], [offer]).hex() - - -def abi_encode_node(node_id, left, right): - node = (_bytes32(node_id), _bytes32(left), _bytes32(right)) - return "0x" + encode([INTERNAL_NODE_ABI_TYPE], [node]).hex() - - -def hash_collateral_params(cp): - return _keccak_abi( - ["bytes32", "address", "uint256", "uint256", "address"], - [ - COLLATERAL_PARAMS_TYPEHASH, - w3.to_checksum_address(cp["token"]), - int(cp["lltv"]), - int(cp["liquidationCursor"]), - w3.to_checksum_address(cp["oracle"]), - ], - ) - - -def hash_market(m): - collateral_params_hashes = b"".join( - hash_collateral_params(cp) for cp in m["collateralParams"] - ) - collateral_params_hash = w3.keccak(collateral_params_hashes) - return _keccak_abi( - [ - "bytes32", - "uint256", - "address", - "address", - "bytes32", - "uint256", - "uint256", - "address", - "address", - ], - [ - MARKET_TYPEHASH, - int(m["chainId"]), - w3.to_checksum_address(m["midnight"]), - w3.to_checksum_address(m["loanToken"]), - collateral_params_hash, - int(m["maturity"]), - int(m["rcfThreshold"]), - w3.to_checksum_address(m["enterGate"]), - w3.to_checksum_address(m["liquidatorGate"]), - ], - ) - - -# Returns the hash of an offer (mirrors HashLib.hashOffer). -def hash_offer(o): - return w3.to_hex( - _keccak_abi( - [ - "bytes32", - "bytes32", - "bool", - "address", - "uint256", - "uint256", - "uint256", - "bytes32", - "address", - "bytes32", - "address", - "address", - "bool", - "uint128", - "uint128", - "uint256", - ], - [ - OFFER_TYPEHASH, - hash_market(o["market"]), - bool(o["buy"]), - w3.to_checksum_address(o["maker"]), - int(o["start"]), - int(o["expiry"]), - int(o["tick"]), - _bytes32(o["group"]), - w3.to_checksum_address(o["callback"]), - w3.keccak(_hexbytes(o["callbackData"])), - w3.to_checksum_address(o["receiverIfMakerIsSeller"]), - w3.to_checksum_address(o["ratifier"]), - bool(o["reduceOnly"]), - int(o["maxUnits"]), - int(o["maxAssets"]), - int(o["continuousFeeCap"]), - ], - ) - ) - - -# Returns the hash of a node given the hashes of its children. -def hash_node(left, right): - return w3.to_hex(w3.keccak(_bytes32(left) + _bytes32(right))) - - -# Builds a certificate from a power-of-two list of offers, in leftIndex order, by pairing -# leaves level-by-level into a perfect binary tree. -def build_certificate(leaves, claimed_root): - n = len(leaves) - _require(n > 0 and (n & (n - 1)) == 0, "leaves count must be a power of two") - - leaf_instructions = {} - node_instructions = {} - - level = [hash_offer(o) for o in leaves] - for leaf, leaf_hash in zip(leaves, level): - encoded_leaf = abi_encode_offer(leaf) - previous = leaf_instructions.setdefault(leaf_hash, encoded_leaf) - _require(previous == encoded_leaf, "leaf hash collides with a different offer") - - while len(level) > 1: - next_level = [] - for i in range(len(level) // 2): - left = level[2 * i] - right = level[2 * i + 1] - node_hash = hash_node(left, right) - _require(node_hash not in leaf_instructions, "internal node id collides with a leaf id") - encoded_node = abi_encode_node(node_hash, left, right) - previous = node_instructions.setdefault(node_hash, encoded_node) - _require(previous == encoded_node, "internal node id collides with different children") - next_level.append(node_hash) - level = next_level - - _require( - level[0].lower() == claimed_root.lower(), - f"computed root {level[0]} != claimed root {claimed_root}", - ) - - return { - "root": claimed_root, - "leafLength": len(leaf_instructions), - "leaf": list(leaf_instructions.values()), - "nodeLength": len(node_instructions), - "node": list(node_instructions.values()), - } - - -def main(): - if len(sys.argv) != 2: - print("usage: python create_certificate.py ", file=sys.stderr) - sys.exit(2) - - _check_typehashes() - - with open(sys.argv[1]) as f: - proofs = json.load(f) - - root = proofs["root"] - certificate = build_certificate([entry["offer"] for entry in proofs["leaves"]], root) - - with open("certificate.json", "w") as f: - json.dump(certificate, f, indent=2) - - -if __name__ == "__main__": - main() diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index 4c4844f10..0a64a2bbd 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -1,10 +1,8 @@ { "files": [ - "src/Midnight.sol", - "certora/helpers/OfferTree.sol", - "certora/helpers/Utils.sol" + "certora/helpers/OfferTree.sol" ], - "verify": "Midnight:certora/specs/OfferTreeMembership.spec", + "verify": "OfferTree:certora/specs/OfferTreeMembership.spec", "solc": "solc-0.8.34", "solc_via_ir": true, "solc_optimize": "200", diff --git a/certora/confs/Ratification.conf b/certora/confs/Ratification.conf index 1a2010582..63238717c 100644 --- a/certora/confs/Ratification.conf +++ b/certora/confs/Ratification.conf @@ -12,6 +12,7 @@ "verify": "Midnight:certora/specs/Ratification.spec", "solc": "solc-0.8.34", "solc_via_ir": true, + "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, "loop_iter": 2, diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index f4957a592..7f25328a9 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -50,7 +50,7 @@ contract OfferTree { // Leaves keep the fixed-size pre-image of hashOffer (see Leaf) so isWellFormed can recompute a leaf's hash // and pin its hashNode into the image of hashOffer. hashOffer and hashNode feed keccak distinct // input shapes, this gives domain separation between leaves and internal nodes. The tree is built only via newLeaf - // and newInternalNode, which preserve well-formedness by construction. + // and newInternalNode (directly or through generateRoot), which preserve well-formedness by construction. mapping(bytes32 => Node) internal tree; /* MAIN FUNCTIONS */ @@ -93,6 +93,47 @@ contract OfferTree { n.hashNode = HashLib.hashNode(leftHash, rightHash); } + // Build a perfect binary tree from a non-empty, power-of-two list of offers and return its root. + // Duplicate leaves and subtrees share the same node because their identifiers are their hashes. + function generateRoot(Offer[] memory leaves) public returns (bytes32) { + require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); + + bytes32[] memory level = new bytes32[](leaves.length); + for (uint256 i = 0; i < leaves.length; i++) { + bytes32 leafHash = HashLib.hashOffer(leaves[i]); + if (_isEmpty(tree[leafHash])) { + newLeaf(leaves[i]); + } else { + require(isLeafNode(leafHash), "leaf id collision"); + } + level[i] = leafHash; + } + + while (level.length > 1) { + uint256 nextLength = level.length / 2; + bytes32[] memory next = new bytes32[](nextLength); + + for (uint256 i = 0; i < nextLength; i++) { + bytes32 left = level[2 * i]; + bytes32 right = level[2 * i + 1]; + bytes32 nodeHash = HashLib.hashNode(left, right); + Node storage n = tree[nodeHash]; + if (_isEmpty(n)) { + newInternalNode(nodeHash, left, right); + } else { + require( + n.left == left && n.right == right && n.hashNode == nodeHash, "internal node id collision" + ); + } + next[i] = nodeHash; + } + + level = next; + } + + return level[0]; + } + /* PURE AND VIEW FUNCTIONS */ function _isEmpty(Node storage n) internal view returns (bool) { @@ -119,6 +160,14 @@ contract OfferTree { return HashLib.hashNode(left, right); } + function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) + public + pure + returns (bool) + { + return HashLib.isLeaf(root, leafHash, leafIndex, proof); + } + function _hashLeaf(bytes32 id) public view returns (bytes32) { return _hashLeaf(tree[id].leaf); } diff --git a/certora/helpers/Utils.sol b/certora/helpers/Utils.sol index 7a4d1643b..6a00c934f 100644 --- a/certora/helpers/Utils.sol +++ b/certora/helpers/Utils.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {Offer, Market} from "../../src/interfaces/IMidnight.sol"; import {UtilsLib} from "../../src/libraries/UtilsLib.sol"; -import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; import {IdLib} from "../../src/libraries/IdLib.sol"; import { CALLBACK_SUCCESS, @@ -19,23 +18,7 @@ contract Utils { } function hashMarket(Market memory market) external pure returns (bytes32) { - return HashLib.hashMarket(market); - } - - // Wraps `HashLib.hashOffer` directly so CVL specs can expose the real EIP-712 offer hash - // envfree. Used by OfferTreeMembership.spec as the leaf id. A `keccak256(abi.encode(offer))` - // reimplementation would be a *different* hash (no typehash prefix, no inner hashing of - // market/callbackData), so we forward to the real library function. - function hashOffer(Offer memory offer) external pure returns (bytes32) { - return HashLib.hashOffer(offer); - } - - function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) - external - pure - returns (bool) - { - return HashLib.isLeaf(root, leafHash, leafIndex, proof); + return keccak256(abi.encode(market)); } function getBit(uint128 bitmap, uint256 bit) external pure returns (bool) { diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 7256cdc43..8be93cba9 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -1,28 +1,25 @@ // SPDX-License-Identifier: GPL-2.0-or-later -using OfferTree as OfferTree; -using Utils as Utils; - methods { - function OfferTree.getHash(bytes32) external returns (bytes32) envfree; - function OfferTree.isLeafNode(bytes32) external returns (bool) envfree; - function OfferTree.wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; - function Utils.hashOffer(Midnight.Offer) external returns (bytes32) envfree; - function Utils.isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; + function getHash(bytes32) external returns (bytes32) envfree; + function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; + function isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; + function isLeafNode(bytes32) external returns (bool) envfree; + function wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; } // Headline Correctness Rule: // If the root is setup according to a well-formed offer tree, then a successful Merkle verification of an offer against that root implies the offer is registered as a leaf in the tree. -rule membershipSoundness(Midnight.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { +rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; - require OfferTree.getHash(node) == root, "root is the hash of node"; + require getHash(node) == root, "root is the hash of node"; - require(OfferTree.wellFormedPath(node, leafIndex, proof), "the path from the root to the leaf is well-formed"); + require wellFormedPath(node, leafIndex, proof), "the path from the root to the leaf is well-formed"; - bytes32 leafId = Utils.hashOffer(offer); + bytes32 leafId = hashOffer(offer); - require Utils.isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; + require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; - assert OfferTree.isLeafNode(leafId); + assert isLeafNode(leafId); } diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 0c87937e0..5b9ea0d81 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -8,6 +8,7 @@ // properties (leaf/internal domain separation, hashNode injectivity) that OfferTreeMembership.spec relies on. methods { + function generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; function newLeaf(OfferTree.Offer) external envfree; function _hashLeaf(bytes32) external returns (bytes32) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index 323da2581..058031adf 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -10,7 +10,7 @@ methods { function Utils.callbackSuccess() external returns (bytes32) envfree; - function _.isRatified(Midnight.Offer, bytes) external => DISPATCHER(true); + function _.isRatified(Midnight.Offer, bytes, address) external => DISPATCHER(true); function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; function _.transferFrom(address, address, uint256) external => NONDET; @@ -74,10 +74,10 @@ rule takeRequiresNonZeroMaker(env e, Midnight.Offer offer, bytes ratifierData, u } /// Every successful isRatified call implies HashLib.isLeaf was invoked and returned true. Verified by dispatch across all linked ratifier implementations. -rule isRatifiedRequiresIsLeaf(env e, address ratifierAddr, Midnight.Offer offer, bytes ratifierData) { +rule isRatifiedRequiresIsLeaf(env e, address ratifierAddr, Midnight.Offer offer, bytes ratifierData, address taker) { require !isLeafReturnedTrue, "fresh capture state"; - bytes32 result = ratifierAddr.isRatified(e, offer, ratifierData); + bytes32 result = ratifierAddr.isRatified(e, offer, ratifierData, taker); require result == Utils.callbackSuccess(), "isRatified succeeded"; assert isLeafReturnedTrue, "ratifier must have called HashLib.isLeaf that returned true"; diff --git a/foundry.toml b/foundry.toml index 52ed4c6fc..cf019ab67 100644 --- a/foundry.toml +++ b/foundry.toml @@ -12,11 +12,6 @@ fs_permissions = [ [profile.default.fmt] wrap_comments = true -[profile.checker] -test = "certora/checker" -match_contract = "Checker" -fs_permissions = [{ access = "read", path = "./" }] - [lint] exclude_lints = [ "asm-keccak256", From a52e7acfdb85720e5852d6deaf48f073e3b55626 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 31 Aug 2026 23:03:57 +0200 Subject: [PATCH 144/159] trimmed comments --- certora/confs/Ratification.conf | 10 +----- certora/helpers/OfferTree.sol | 45 +++++------------------- certora/specs/OfferTreeMembership.spec | 3 +- certora/specs/OfferTreeWellFormed.spec | 18 ++++------ certora/specs/Ratification.spec | 47 -------------------------- 5 files changed, 16 insertions(+), 107 deletions(-) diff --git a/certora/confs/Ratification.conf b/certora/confs/Ratification.conf index 63238717c..a8edd78fd 100644 --- a/certora/confs/Ratification.conf +++ b/certora/confs/Ratification.conf @@ -1,18 +1,10 @@ { "files": [ - "src/Midnight.sol", - "src/ratifiers/EcrecoverRatifier.sol", - "src/ratifiers/SetterRatifier.sol", - "certora/helpers/Utils.sol" - ], - "link": [ - "EcrecoverRatifier:MIDNIGHT=Midnight", - "SetterRatifier:MIDNIGHT=Midnight" + "src/Midnight.sol" ], "verify": "Midnight:certora/specs/Ratification.spec", "solc": "solc-0.8.34", "solc_via_ir": true, - "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, "loop_iter": 2, diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 7f25328a9..08d251f00 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -5,14 +5,8 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib, OFFER_TYPEHASH} from "../../src/ratifiers/libraries/HashLib.sol"; -// A leaf's offer reaches HashLib.hashOffer only through fixed-size fields: every dynamic member of Offer -// (market.collateralParams and callbackData) is already reduced to a single bytes32 before the final -// keccak (hashMarket(market) and keccak256(callbackData)). So we store that fixed-size pre-image instead -// of the raw Offer. This keeps every Node fixed-size, so isWellFormed re-hashes a leaf with one bounded -// keccak (no dynamic-array reads, no loops) — the property that lets the wellFormed invariant scale, exactly -// as it does for URD's fixed-size leaves. _hashLeaf mirrors hashOffer's outer keccak field-for-field, so a -// leaf's id is the real hashOffer value; the wellFormed invariant's newLeaf case checks this mirror holds -// (id == hashOffer(offer) and id == _hashLeaf(leaf)), so the correspondence is verified, not assumed. +// Fixed-size pre-image of HashLib.hashOffer. Dynamic fields are stored as hashes so CVL can re-hash a leaf +// without iterating over dynamic data. struct Leaf { bytes32 marketHash; // = HashLib.hashMarket(offer.market) bool buy; @@ -36,31 +30,18 @@ contract OfferTree { bytes32 left; bytes32 right; Leaf leaf; - // hash of the offer for leaves, and of [left.hash, right.hash] for internal nodes. + // Offer hash for leaves and hash of the children for internal nodes. bytes32 hashNode; } - /* STORAGE */ - - // The tree has no root because every node (and the nodes underneath) form an offer tree. - // We use bytes32 as keys of the mapping so that leaves have an identifier that is the hash of the offer. - // Identical offers therefore share a single node (referenced by multiple parents). - // For internal nodes the key is left arbitrary, so that the certificate generation can choose freely any bytes32 - // value (that is not already used). - // Leaves keep the fixed-size pre-image of hashOffer (see Leaf) so isWellFormed can recompute a leaf's hash - // and pin its hashNode into the image of hashOffer. hashOffer and hashNode feed keccak distinct - // input shapes, this gives domain separation between leaves and internal nodes. The tree is built only via newLeaf - // and newInternalNode (directly or through generateRoot), which preserve well-formedness by construction. + // Leaf ids are offer hashes. Internal node ids may be arbitrary. mapping(bytes32 => Node) internal tree; - /* MAIN FUNCTIONS */ - function newLeaf(Offer memory offer) public { bytes32 id = HashLib.hashOffer(offer); require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; require(_isEmpty(n), "leaf is not empty"); - // Store the fixed-size pre-image of hashOffer; the dynamic members are kept only as their sub-hashes. Leaf storage l = n.leaf; l.marketHash = HashLib.hashMarket(offer.market); l.buy = offer.buy; @@ -93,8 +74,7 @@ contract OfferTree { n.hashNode = HashLib.hashNode(leftHash, rightHash); } - // Build a perfect binary tree from a non-empty, power-of-two list of offers and return its root. - // Duplicate leaves and subtrees share the same node because their identifiers are their hashes. + // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. function generateRoot(Offer[] memory leaves) public returns (bytes32) { require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); @@ -134,8 +114,6 @@ contract OfferTree { return level[0]; } - /* PURE AND VIEW FUNCTIONS */ - function _isEmpty(Node storage n) internal view returns (bool) { return n.left == 0 && n.right == 0 && n.hashNode == 0; } @@ -172,9 +150,7 @@ contract OfferTree { return _hashLeaf(tree[id].leaf); } - // Recompute the leaf hash from its stored fixed-size pre-image. Mirrors HashLib.hashOffer's outer keccak - // field-for-field, with marketHash standing in for hashMarket(market) and callbackDataHash for - // keccak256(callbackData). Equals HashLib.hashOffer(offer) whenever the fields were extracted from offer. + // Reconstruct HashLib.hashOffer from the stored pre-image. function _hashLeaf(Leaf storage l) internal view returns (bytes32) { return keccak256( abi.encode( @@ -198,11 +174,7 @@ contract OfferTree { ); } - // The specification of a well-formed tree is the following: - // - empty nodes are well-formed - // - leaves have the correct identifier and hashing - // - internal nodes have the correct hashing - // - internal nodes have exactly two non-empty children + // A node is empty, a correctly hashed leaf, or a correctly hashed internal node with two children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (_isEmpty(n)) return true; @@ -218,8 +190,7 @@ contract OfferTree { return false; } - // Check that the nodes are well-formed starting from id and going down the tree. - // The bits of leafIndex choose the path downward; the depth is proof.length. + // Check the path selected by leafIndex. function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bool) { for (uint256 i = proof.length;;) { require(isWellFormed(id)); diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 8be93cba9..e8cda7f3b 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -8,8 +8,7 @@ methods { function wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; } -// Headline Correctness Rule: -// If the root is setup according to a well-formed offer tree, then a successful Merkle verification of an offer against that root implies the offer is registered as a leaf in the tree. +// A valid proof in a well-formed tree identifies a registered leaf. rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 5b9ea0d81..7d64b84b7 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// Leaves store the fixed-size pre-image of hashOffer (its static fields plus marketHash and callbackDataHash) -// instead of the raw Offer, so isWellFormed re-hashes a leaf with one bounded keccak (_hashLeaf) and the -// wellFormed proof stays bounded regardless of offer size (no dynamic-array loops, no dynamic-length hashing). -// hashLeafReproducesHashOffer justifies the trick: the stored pre-image re-hashes -// to the real hashOffer. leafHashDisjointFromNodeHash and nodeHashInjective record the two keccak-model -// properties (leaf/internal domain separation, hashNode injectivity) that OfferTreeMembership.spec relies on. +// Leaves store a fixed-size pre-image so isWellFormed can re-hash them without dynamic loops. methods { function generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; @@ -17,11 +12,11 @@ methods { function isWellFormed(bytes32) external returns (bool) envfree; } -// The zero node is empty, so it can serve as the canonical empty child of every node in the tree. +// The zero node remains empty. strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); -// Every node of the tree is well-formed, which is what makes the membership result in OfferTreeMembership.spec sound. +// Every node remains well-formed. strong invariant wellFormed(bytes32 id) isWellFormed(id) { @@ -30,8 +25,7 @@ strong invariant wellFormed(bytes32 id) } } -// _hashLeaf reproduces the real hashOffer for the leaf stored by newLeaf. -// newLeaf is called without @withrevert, so its own guards (id != 0, slot empty) hold as assumptions. +// newLeaf stores a pre-image that reproduces hashOffer. rule hashLeafReproducesHashOffer(OfferTree.Offer offer) { newLeaf(offer); @@ -39,12 +33,12 @@ rule hashLeafReproducesHashOffer(OfferTree.Offer offer) { assert _hashLeaf(id) == id; } -// A recomputed leaf hash never equals an internal-node hash: image(_hashLeaf) and image(hashNode) are disjoint. +// Leaf and internal-node hashes have disjoint images. rule leafHashDisjointFromNodeHash(bytes32 id, bytes32 a, bytes32 b) { assert _hashLeaf(id) != hashNode(a, b); } -// hashNode is injective, which the merkle peeling in OfferTreeMembership.spec relies on. +// Internal-node hashing is injective. rule nodeHashInjective(bytes32 a, bytes32 b, bytes32 c, bytes32 d) { require hashNode(a, b) == hashNode(c, d); assert a == c && b == d; diff --git a/certora/specs/Ratification.spec b/certora/specs/Ratification.spec index 058031adf..5cf2a94bb 100644 --- a/certora/specs/Ratification.spec +++ b/certora/specs/Ratification.spec @@ -1,27 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2026 Morpho Association -using Utils as Utils; - methods { function multicall(bytes[]) external => HAVOC_ALL DELETE; function isAuthorized(address authorizer, address authorized) external returns (bool) envfree; - function Utils.callbackSuccess() external returns (bytes32) envfree; - - function _.isRatified(Midnight.Offer, bytes, address) external => DISPATCHER(true); - function _.onBuy(bytes32, Midnight.Market, uint256, uint256, uint256, address, bytes) external => NONDET; - function _.onSell(bytes32, Midnight.Market, uint256, uint256, uint256, address, address, bytes) external => NONDET; - function _.transferFrom(address, address, uint256) external => NONDET; - function _.transfer(address, uint256) external => NONDET; - - // Capture HashLib.isLeaf's return; needed by `isRatifiedRequiresIsLeaf` to assert isRatified gates on a merkle check. - function HashLib.isLeaf(bytes32, bytes32, uint256, bytes32[] memory) internal returns (bool) => isLeafCapture(); - - function HashLib.hashOffer(Midnight.Offer memory) internal returns (bytes32) => NONDET; - function HashLib.offerTreeTypeHash(uint256) internal returns (bytes32) => NONDET; - // Over-approximate view functions. function IdLib.toId(Midnight.Market memory) internal returns (bytes32) => NONDET; function UtilsLib.mulDivDown(uint256, uint256, uint256) internal returns (uint256) => NONDET; @@ -33,18 +17,6 @@ methods { function settlementFee(bytes32, uint256) internal returns (uint256) => NONDET; } -// Captures whether HashLib.isLeaf was called and returned true during the current rule. -// Used by `isRatifiedRequiresIsLeaf` to assert that every successful isRatified gates on a merkle check. -persistent ghost bool isLeafReturnedTrue; - -function isLeafCapture() returns bool { - bool ret; - if (ret) { - isLeafReturnedTrue = true; - } - return ret; -} - /// Every successful take requires the maker to have authorized the ratifier. rule takeRequiresMakerConsent(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { bool makerAuthorizedRatifier = isAuthorized(offer.maker, offer.ratifier); @@ -72,22 +44,3 @@ rule takeRequiresNonZeroMaker(env e, Midnight.Offer offer, bytes ratifierData, u take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); assert offer.maker != 0; } - -/// Every successful isRatified call implies HashLib.isLeaf was invoked and returned true. Verified by dispatch across all linked ratifier implementations. -rule isRatifiedRequiresIsLeaf(env e, address ratifierAddr, Midnight.Offer offer, bytes ratifierData, address taker) { - require !isLeafReturnedTrue, "fresh capture state"; - - bytes32 result = ratifierAddr.isRatified(e, offer, ratifierData, taker); - require result == Utils.callbackSuccess(), "isRatified succeeded"; - - assert isLeafReturnedTrue, "ratifier must have called HashLib.isLeaf that returned true"; -} - -/// Every successful Midnight.take implies HashLib.isLeaf was invoked and returned true. -rule takeRequiresIsLeaf(env e, Midnight.Offer offer, bytes ratifierData, uint256 units, address taker, address receiverIfTakerIsSeller, address takerCallback, bytes takerCallbackData) { - require !isLeafReturnedTrue, "fresh capture state"; - - take(e, offer, ratifierData, units, taker, receiverIfTakerIsSeller, takerCallback, takerCallbackData); - - assert isLeafReturnedTrue, "take must have triggered a ratifier that called HashLib.isLeaf returning true"; -} From a258ed6acbfcb8dbde0500ccb4194e2aa61a459d Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 31 Aug 2026 23:16:36 +0200 Subject: [PATCH 145/159] removed leafHashDisjointFromNodeHash and nodeHashInjective --- certora/specs/OfferTreeWellFormed.spec | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 7d64b84b7..27214b0ce 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -7,7 +7,6 @@ methods { function newLeaf(OfferTree.Offer) external envfree; function _hashLeaf(bytes32) external returns (bytes32) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; - function hashNode(bytes32, bytes32) external returns (bytes32) envfree; function isEmpty(bytes32) external returns (bool) envfree; function isWellFormed(bytes32) external returns (bool) envfree; } @@ -32,14 +31,3 @@ rule hashLeafReproducesHashOffer(OfferTree.Offer offer) { bytes32 id = hashOffer(offer); assert _hashLeaf(id) == id; } - -// Leaf and internal-node hashes have disjoint images. -rule leafHashDisjointFromNodeHash(bytes32 id, bytes32 a, bytes32 b) { - assert _hashLeaf(id) != hashNode(a, b); -} - -// Internal-node hashing is injective. -rule nodeHashInjective(bytes32 a, bytes32 b, bytes32 c, bytes32 d) { - require hashNode(a, b) == hashNode(c, d); - assert a == c && b == d; -} From f6cbe2fb144321bd24358a6003c87227e7c035fe Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 31 Aug 2026 23:26:57 +0200 Subject: [PATCH 146/159] fmt --- certora/specs/OfferTreeMembership.spec | 4 ---- 1 file changed, 4 deletions(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index e8cda7f3b..ed549a2b2 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -11,13 +11,9 @@ methods { // A valid proof in a well-formed tree identifies a registered leaf. rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; - require getHash(node) == root, "root is the hash of node"; - require wellFormedPath(node, leafIndex, proof), "the path from the root to the leaf is well-formed"; - bytes32 leafId = hashOffer(offer); - require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; assert isLeafNode(leafId); From c0e2d9281b4c3a17573216f826826baedc33d2f4 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 31 Aug 2026 23:30:35 +0200 Subject: [PATCH 147/159] tuned --- certora/specs/OfferTreeMembership.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index ed549a2b2..27fd32299 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -8,7 +8,7 @@ methods { function wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; } -// A valid proof in a well-formed tree identifies a registered leaf. +// Soundness: if a Merkle proof verifies along a well-formed path, hashOffer(offer) must be a leaf node. rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; require getHash(node) == root, "root is the hash of node"; From a539e6688362808cdfc63b2355e86f5af6485e1e Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 1 Sep 2026 00:26:24 +0200 Subject: [PATCH 148/159] removed hashLeafReproducesHashOffer --- certora/helpers/OfferTree.sol | 73 +++++++++++--------------- certora/specs/OfferTreeMembership.spec | 4 +- certora/specs/OfferTreeWellFormed.spec | 11 ---- 3 files changed, 33 insertions(+), 55 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 08d251f00..1001a54e7 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -31,7 +31,7 @@ contract OfferTree { bytes32 right; Leaf leaf; // Offer hash for leaves and hash of the children for internal nodes. - bytes32 hashNode; + bytes32 hash; } // Leaf ids are offer hashes. Internal node ids may be arbitrary. @@ -41,7 +41,7 @@ contract OfferTree { bytes32 id = HashLib.hashOffer(offer); require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; - require(_isEmpty(n), "leaf is not empty"); + require(isEmpty(n), "leaf is not empty"); Leaf storage l = n.leaf; l.marketHash = HashLib.hashMarket(offer.market); l.buy = offer.buy; @@ -58,20 +58,22 @@ contract OfferTree { l.maxUnits = offer.maxUnits; l.maxAssets = offer.maxAssets; l.continuousFeeCap = offer.continuousFeeCap; - n.hashNode = id; + n.hash = id; } function newInternalNode(bytes32 id, bytes32 left, bytes32 right) public { require(id != 0, "zero id"); Node storage n = tree[id]; - require(_isEmpty(n), "node already populated"); - bytes32 leftHash = tree[left].hashNode; - bytes32 rightHash = tree[right].hashNode; + require(isEmpty(n), "node already populated"); + bytes32 leftHash = tree[left].hash; + bytes32 rightHash = tree[right].hash; require(leftHash != 0, "left empty"); require(rightHash != 0, "right empty"); + bytes32 hash = HashLib.hashNode(leftHash, rightHash); + require(hash != 0, "zero hash"); n.left = left; n.right = right; - n.hashNode = HashLib.hashNode(leftHash, rightHash); + n.hash = hash; } // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. @@ -81,7 +83,7 @@ contract OfferTree { bytes32[] memory level = new bytes32[](leaves.length); for (uint256 i = 0; i < leaves.length; i++) { bytes32 leafHash = HashLib.hashOffer(leaves[i]); - if (_isEmpty(tree[leafHash])) { + if (isEmpty(tree[leafHash])) { newLeaf(leaves[i]); } else { require(isLeafNode(leafHash), "leaf id collision"); @@ -89,55 +91,46 @@ contract OfferTree { level[i] = leafHash; } - while (level.length > 1) { - uint256 nextLength = level.length / 2; - bytes32[] memory next = new bytes32[](nextLength); - - for (uint256 i = 0; i < nextLength; i++) { + uint256 levelLength = level.length; + while (levelLength > 1) { + levelLength /= 2; + for (uint256 i = 0; i < levelLength; i++) { bytes32 left = level[2 * i]; bytes32 right = level[2 * i + 1]; bytes32 nodeHash = HashLib.hashNode(left, right); Node storage n = tree[nodeHash]; - if (_isEmpty(n)) { + if (isEmpty(n)) { newInternalNode(nodeHash, left, right); } else { - require( - n.left == left && n.right == right && n.hashNode == nodeHash, "internal node id collision" - ); + require(n.left == left && n.right == right && n.hash == nodeHash, "internal node id collision"); } - next[i] = nodeHash; + level[i] = nodeHash; } - - level = next; } return level[0]; } - function _isEmpty(Node storage n) internal view returns (bool) { - return n.left == 0 && n.right == 0 && n.hashNode == 0; + function isEmpty(Node storage n) internal view returns (bool) { + return n.hash == 0; } function isEmpty(bytes32 id) public view returns (bool) { - return _isEmpty(tree[id]); + return isEmpty(tree[id]); } function getHash(bytes32 id) public view returns (bytes32) { - return tree[id].hashNode; + return tree[id].hash; } function isLeafNode(bytes32 id) public view returns (bool) { - return tree[id].left == 0 && tree[id].right == 0 && tree[id].hashNode != 0; + return tree[id].left == 0 && tree[id].right == 0 && tree[id].hash != 0; } function hashOffer(Offer memory offer) public pure returns (bytes32) { return HashLib.hashOffer(offer); } - function hashNode(bytes32 left, bytes32 right) public pure returns (bytes32) { - return HashLib.hashNode(left, right); - } - function isLeaf(bytes32 root, bytes32 leafHash, uint256 leafIndex, bytes32[] memory proof) public pure @@ -146,12 +139,8 @@ contract OfferTree { return HashLib.isLeaf(root, leafHash, leafIndex, proof); } - function _hashLeaf(bytes32 id) public view returns (bytes32) { - return _hashLeaf(tree[id].leaf); - } - // Reconstruct HashLib.hashOffer from the stored pre-image. - function _hashLeaf(Leaf storage l) internal view returns (bytes32) { + function hashLeaf(Leaf storage l) internal view returns (bytes32) { return keccak256( abi.encode( OFFER_TYPEHASH, @@ -177,22 +166,22 @@ contract OfferTree { // A node is empty, a correctly hashed leaf, or a correctly hashed internal node with two children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; - if (_isEmpty(n)) return true; + if (isEmpty(n)) return true; if (n.left == 0 && n.right == 0) { - bytes32 expected = _hashLeaf(n.leaf); - return n.hashNode == expected && id == expected; + bytes32 expected = hashLeaf(n.leaf); + return n.hash == expected && id == expected; } if (n.left != 0 && n.right != 0) { - bytes32 leftHash = tree[n.left].hashNode; - bytes32 rightHash = tree[n.right].hashNode; - return leftHash != 0 && rightHash != 0 && n.hashNode == HashLib.hashNode(leftHash, rightHash); + bytes32 leftHash = tree[n.left].hash; + bytes32 rightHash = tree[n.right].hash; + return leftHash != 0 && rightHash != 0 && n.hash == HashLib.hashNode(leftHash, rightHash); } return false; } // Check the path selected by leafIndex. - function wellFormedPath(bytes32 id, uint256 leafIndex, bytes32[] memory proof) public view returns (bool) { - for (uint256 i = proof.length;;) { + function wellFormedPath(bytes32 id, uint256 leafIndex, uint256 depth) public view returns (bool) { + for (uint256 i = depth;;) { require(isWellFormed(id)); if (i == 0) break; diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 27fd32299..59481b54c 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -5,14 +5,14 @@ methods { function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; function isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; function isLeafNode(bytes32) external returns (bool) envfree; - function wellFormedPath(bytes32, uint256, bytes32[]) external returns (bool) envfree; + function wellFormedPath(bytes32, uint256, uint256) external returns (bool) envfree; } // Soundness: if a Merkle proof verifies along a well-formed path, hashOffer(offer) must be a leaf node. rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { bytes32 node; require getHash(node) == root, "root is the hash of node"; - require wellFormedPath(node, leafIndex, proof), "the path from the root to the leaf is well-formed"; + require wellFormedPath(node, leafIndex, proof.length), "the path from the root to the leaf is well-formed"; bytes32 leafId = hashOffer(offer); require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 27214b0ce..b7f8f87b8 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -4,9 +4,6 @@ methods { function generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; - function newLeaf(OfferTree.Offer) external envfree; - function _hashLeaf(bytes32) external returns (bytes32) envfree; - function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; function isEmpty(bytes32) external returns (bool) envfree; function isWellFormed(bytes32) external returns (bool) envfree; } @@ -23,11 +20,3 @@ strong invariant wellFormed(bytes32 id) requireInvariant zeroIsEmpty(); } } - -// newLeaf stores a pre-image that reproduces hashOffer. -rule hashLeafReproducesHashOffer(OfferTree.Offer offer) { - newLeaf(offer); - - bytes32 id = hashOffer(offer); - assert _hashLeaf(id) == id; -} From b5870a983c5cfda34f9def5b9ff945d782dda819 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 1 Sep 2026 10:32:35 +0200 Subject: [PATCH 149/159] factored out generate root; restored empty leaf condition --- certora/helpers/GenerateRoot.sol | 44 ++++++++++++++++++++++++++ certora/helpers/OfferTree.sol | 37 +--------------------- certora/specs/OfferTreeWellFormed.spec | 1 - 3 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 certora/helpers/GenerateRoot.sol diff --git a/certora/helpers/GenerateRoot.sol b/certora/helpers/GenerateRoot.sol new file mode 100644 index 000000000..c76239855 --- /dev/null +++ b/certora/helpers/GenerateRoot.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2025 Morpho Association +pragma solidity ^0.8.0; + +import {OfferTree} from "./OfferTree.sol"; +import {Offer} from "../../src/interfaces/IMidnight.sol"; +import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; + +contract GenerateRoot is OfferTree { + // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. + function generateRoot(Offer[] memory leaves) public returns (bytes32) { + require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); + + bytes32[] memory level = new bytes32[](leaves.length); + for (uint256 i = 0; i < leaves.length; i++) { + bytes32 leafHash = HashLib.hashOffer(leaves[i]); + if (isEmpty(tree[leafHash])) { + newLeaf(leaves[i]); + } else { + require(isLeafNode(leafHash), "leaf id collision"); + } + level[i] = leafHash; + } + + uint256 levelLength = level.length; + while (levelLength > 1) { + levelLength /= 2; + for (uint256 i = 0; i < levelLength; i++) { + bytes32 left = level[2 * i]; + bytes32 right = level[2 * i + 1]; + bytes32 nodeHash = HashLib.hashNode(left, right); + Node storage n = tree[nodeHash]; + if (isEmpty(n)) { + newInternalNode(nodeHash, left, right); + } else { + require(n.left == left && n.right == right && n.hash == nodeHash, "internal node id collision"); + } + level[i] = nodeHash; + } + } + + return level[0]; + } +} diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 1001a54e7..868960bc5 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -76,41 +76,6 @@ contract OfferTree { n.hash = hash; } - // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. - function generateRoot(Offer[] memory leaves) public returns (bytes32) { - require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); - - bytes32[] memory level = new bytes32[](leaves.length); - for (uint256 i = 0; i < leaves.length; i++) { - bytes32 leafHash = HashLib.hashOffer(leaves[i]); - if (isEmpty(tree[leafHash])) { - newLeaf(leaves[i]); - } else { - require(isLeafNode(leafHash), "leaf id collision"); - } - level[i] = leafHash; - } - - uint256 levelLength = level.length; - while (levelLength > 1) { - levelLength /= 2; - for (uint256 i = 0; i < levelLength; i++) { - bytes32 left = level[2 * i]; - bytes32 right = level[2 * i + 1]; - bytes32 nodeHash = HashLib.hashNode(left, right); - Node storage n = tree[nodeHash]; - if (isEmpty(n)) { - newInternalNode(nodeHash, left, right); - } else { - require(n.left == left && n.right == right && n.hash == nodeHash, "internal node id collision"); - } - level[i] = nodeHash; - } - } - - return level[0]; - } - function isEmpty(Node storage n) internal view returns (bool) { return n.hash == 0; } @@ -166,7 +131,7 @@ contract OfferTree { // A node is empty, a correctly hashed leaf, or a correctly hashed internal node with two children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; - if (isEmpty(n)) return true; + if (isEmpty(n)) return n.left == 0 && n.right == 0; if (n.left == 0 && n.right == 0) { bytes32 expected = hashLeaf(n.leaf); return n.hash == expected && id == expected; diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index b7f8f87b8..1ac844331 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -3,7 +3,6 @@ // Leaves store a fixed-size pre-image so isWellFormed can re-hash them without dynamic loops. methods { - function generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; function isEmpty(bytes32) external returns (bool) envfree; function isWellFormed(bytes32) external returns (bool) envfree; } From 588da4a447508bdbbe5e5a6361a97110c54da905 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 13:13:41 +0200 Subject: [PATCH 150/159] remove smt_timeout from configs --- certora/confs/OfferTreeMembership.conf | 2 -- certora/confs/OfferTreeWellFormed.conf | 2 -- 2 files changed, 4 deletions(-) diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index 0a64a2bbd..c5511a2ae 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -11,8 +11,6 @@ "loop_iter": 3, "optimistic_hashing": true, "hashing_length_bound": 1024, - "rule_sanity": "basic", - "smt_timeout": 7200, "prover_args": [ "-splitParallel true", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf index d0b8fb08b..91dd53cdf 100644 --- a/certora/confs/OfferTreeWellFormed.conf +++ b/certora/confs/OfferTreeWellFormed.conf @@ -11,8 +11,6 @@ "loop_iter": 3, "optimistic_hashing": true, "hashing_length_bound": 1024, - "rule_sanity": "basic", - "smt_timeout": 7200, "prover_args": [ "-splitParallel true", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" From 98c9332e8bcf366c612148c6a294faac5b3ffea0 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 13:44:17 +0200 Subject: [PATCH 151/159] model simplified: node ID is the hash --- certora/helpers/GenerateRoot.sol | 9 ++------- certora/helpers/OfferTree.sol | 19 +++++++++---------- certora/specs/OfferTreeMembership.spec | 7 +++---- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/certora/helpers/GenerateRoot.sol b/certora/helpers/GenerateRoot.sol index c76239855..66b0207af 100644 --- a/certora/helpers/GenerateRoot.sol +++ b/certora/helpers/GenerateRoot.sol @@ -16,8 +16,6 @@ contract GenerateRoot is OfferTree { bytes32 leafHash = HashLib.hashOffer(leaves[i]); if (isEmpty(tree[leafHash])) { newLeaf(leaves[i]); - } else { - require(isLeafNode(leafHash), "leaf id collision"); } level[i] = leafHash; } @@ -29,11 +27,8 @@ contract GenerateRoot is OfferTree { bytes32 left = level[2 * i]; bytes32 right = level[2 * i + 1]; bytes32 nodeHash = HashLib.hashNode(left, right); - Node storage n = tree[nodeHash]; - if (isEmpty(n)) { - newInternalNode(nodeHash, left, right); - } else { - require(n.left == left && n.right == right && n.hash == nodeHash, "internal node id collision"); + if (isEmpty(nodeHash)) { + newInternalNode(left, right); } level[i] = nodeHash; } diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 868960bc5..0b68a1428 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -34,7 +34,7 @@ contract OfferTree { bytes32 hash; } - // Leaf ids are offer hashes. Internal node ids may be arbitrary. + // Every populated node is keyed by its hash. mapping(bytes32 => Node) internal tree; function newLeaf(Offer memory offer) public { @@ -61,19 +61,18 @@ contract OfferTree { n.hash = id; } - function newInternalNode(bytes32 id, bytes32 left, bytes32 right) public { - require(id != 0, "zero id"); - Node storage n = tree[id]; - require(isEmpty(n), "node already populated"); + function newInternalNode(bytes32 left, bytes32 right) public returns (bytes32 id) { bytes32 leftHash = tree[left].hash; bytes32 rightHash = tree[right].hash; require(leftHash != 0, "left empty"); require(rightHash != 0, "right empty"); - bytes32 hash = HashLib.hashNode(leftHash, rightHash); - require(hash != 0, "zero hash"); + id = HashLib.hashNode(leftHash, rightHash); + require(id != 0, "zero hash"); + Node storage n = tree[id]; + require(isEmpty(n), "node already populated"); n.left = left; n.right = right; - n.hash = hash; + n.hash = id; } function isEmpty(Node storage n) internal view returns (bool) { @@ -128,7 +127,7 @@ contract OfferTree { ); } - // A node is empty, a correctly hashed leaf, or a correctly hashed internal node with two children. + // Populated nodes have their hash as identifier and hash their leaf data or their two non-empty children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (isEmpty(n)) return n.left == 0 && n.right == 0; @@ -139,7 +138,7 @@ contract OfferTree { if (n.left != 0 && n.right != 0) { bytes32 leftHash = tree[n.left].hash; bytes32 rightHash = tree[n.right].hash; - return leftHash != 0 && rightHash != 0 && n.hash == HashLib.hashNode(leftHash, rightHash); + return leftHash != 0 && rightHash != 0 && n.hash == id && n.hash == HashLib.hashNode(leftHash, rightHash); } return false; } diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 59481b54c..135ed5518 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later methods { - function getHash(bytes32) external returns (bytes32) envfree; + function isEmpty(bytes32) external returns (bool) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; function isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; function isLeafNode(bytes32) external returns (bool) envfree; @@ -10,9 +10,8 @@ methods { // Soundness: if a Merkle proof verifies along a well-formed path, hashOffer(offer) must be a leaf node. rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, bytes32[] proof) { - bytes32 node; - require getHash(node) == root, "root is the hash of node"; - require wellFormedPath(node, leafIndex, proof.length), "the path from the root to the leaf is well-formed"; + require !isEmpty(root), "root is a populated node"; + require wellFormedPath(root, leafIndex, proof.length), "the path from the root to the leaf is well-formed"; bytes32 leafId = hashOffer(offer); require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; From 0ec785d88572d426247dcef84900cd4d3ff93e4d Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 14:29:08 +0200 Subject: [PATCH 152/159] make offerTree creation idempotent --- certora/helpers/GenerateRoot.sol | 15 +----- certora/helpers/OfferTree.sol | 10 ++-- test/OfferTreeTest.sol | 83 ++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 test/OfferTreeTest.sol diff --git a/certora/helpers/GenerateRoot.sol b/certora/helpers/GenerateRoot.sol index 66b0207af..7e8efd774 100644 --- a/certora/helpers/GenerateRoot.sol +++ b/certora/helpers/GenerateRoot.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {OfferTree} from "./OfferTree.sol"; import {Offer} from "../../src/interfaces/IMidnight.sol"; -import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; contract GenerateRoot is OfferTree { // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. @@ -13,24 +12,14 @@ contract GenerateRoot is OfferTree { bytes32[] memory level = new bytes32[](leaves.length); for (uint256 i = 0; i < leaves.length; i++) { - bytes32 leafHash = HashLib.hashOffer(leaves[i]); - if (isEmpty(tree[leafHash])) { - newLeaf(leaves[i]); - } - level[i] = leafHash; + level[i] = newLeaf(leaves[i]); } uint256 levelLength = level.length; while (levelLength > 1) { levelLength /= 2; for (uint256 i = 0; i < levelLength; i++) { - bytes32 left = level[2 * i]; - bytes32 right = level[2 * i + 1]; - bytes32 nodeHash = HashLib.hashNode(left, right); - if (isEmpty(nodeHash)) { - newInternalNode(left, right); - } - level[i] = nodeHash; + level[i] = newInternalNode(level[2 * i], level[2 * i + 1]); } } diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 0b68a1428..714a2826c 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -37,11 +37,12 @@ contract OfferTree { // Every populated node is keyed by its hash. mapping(bytes32 => Node) internal tree; - function newLeaf(Offer memory offer) public { - bytes32 id = HashLib.hashOffer(offer); + // Create a leaf or return its existing hash ID. + function newLeaf(Offer memory offer) public returns (bytes32 id) { + id = HashLib.hashOffer(offer); require(id != 0, "id is the zero bytes"); Node storage n = tree[id]; - require(isEmpty(n), "leaf is not empty"); + if (!isEmpty(n)) return id; Leaf storage l = n.leaf; l.marketHash = HashLib.hashMarket(offer.market); l.buy = offer.buy; @@ -61,6 +62,7 @@ contract OfferTree { n.hash = id; } + // Create an internal node or return its existing hash ID. function newInternalNode(bytes32 left, bytes32 right) public returns (bytes32 id) { bytes32 leftHash = tree[left].hash; bytes32 rightHash = tree[right].hash; @@ -69,7 +71,7 @@ contract OfferTree { id = HashLib.hashNode(leftHash, rightHash); require(id != 0, "zero hash"); Node storage n = tree[id]; - require(isEmpty(n), "node already populated"); + if (!isEmpty(n)) return id; n.left = left; n.right = right; n.hash = id; diff --git a/test/OfferTreeTest.sol b/test/OfferTreeTest.sol new file mode 100644 index 000000000..4890e4782 --- /dev/null +++ b/test/OfferTreeTest.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2026 Morpho Association +pragma solidity ^0.8.0; + +import {Test} from "../lib/forge-std/src/Test.sol"; +import {GenerateRoot} from "../certora/helpers/GenerateRoot.sol"; +import {Offer} from "../src/interfaces/IMidnight.sol"; +import {HashLib} from "../src/ratifiers/libraries/HashLib.sol"; + +contract OfferTreeTest is Test { + GenerateRoot internal tree; + + function setUp() public { + tree = new GenerateRoot(); + } + + function testGenerateRootWithPrebuiltSubtree(uint256 leftTick, uint256 rightTick) public { + Offer memory leftOffer; + leftOffer.tick = leftTick; + Offer memory rightOffer; + rightOffer.tick = rightTick; + bytes32 left = HashLib.hashOffer(leftOffer); + bytes32 right = HashLib.hashOffer(rightOffer); + assertEq(tree.newLeaf(leftOffer), left); + assertEq(tree.newLeaf(rightOffer), right); + assertEq(tree.newLeaf(leftOffer), left); + assertEq(tree.getHash(left), left); + assertTrue(tree.isLeafNode(left)); + assertTrue(tree.isWellFormed(left)); + + bytes32 parent = tree.newInternalNode(left, right); + assertEq(parent, keccak256(abi.encode(left, right))); + assertEq(tree.newInternalNode(left, right), parent); + assertEq(tree.getHash(parent), parent); + assertTrue(tree.isWellFormed(parent)); + + Offer[] memory offers = new Offer[](4); + offers[0] = leftOffer; + offers[1] = rightOffer; + offers[2] = leftOffer; + offers[3] = rightOffer; + bytes32 root = tree.generateRoot(offers); + assertEq(root, keccak256(abi.encode(parent, parent))); + assertEq(tree.getHash(root), root); + assertTrue(tree.isWellFormed(root)); + + bytes32[] memory proof = new bytes32[](2); + proof[1] = parent; + for (uint256 i = 0; i < offers.length; i++) { + proof[0] = i % 2 == 0 ? right : left; + assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + } + assertEq(tree.generateRoot(offers), root); + } + + function testGenerateRootWithDuplicateSiblings() public { + Offer[] memory offers = new Offer[](4); + bytes32 leaf = HashLib.hashOffer(offers[0]); + bytes32 parent = keccak256(abi.encode(leaf, leaf)); + bytes32 expectedRoot = keccak256(abi.encode(parent, parent)); + + assertEq(tree.generateRoot(offers), expectedRoot); + assertEq(tree.getHash(parent), parent); + assertEq(tree.getHash(expectedRoot), expectedRoot); + assertTrue(tree.isWellFormed(parent)); + assertTrue(tree.isWellFormed(expectedRoot)); + assertEq(tree.generateRoot(offers), expectedRoot); + } + + function testNewInternalNodeRequiresPopulatedChildren() public { + Offer memory offer; + bytes32 leaf = HashLib.hashOffer(offer); + tree.newLeaf(offer); + + vm.expectRevert("left empty"); + tree.newInternalNode(bytes32(0), leaf); + vm.expectRevert("right empty"); + tree.newInternalNode(leaf, bytes32(0)); + + bytes32 parent = tree.newInternalNode(leaf, leaf); + assertEq(tree.getHash(parent), parent); + } +} From a325670d53a84319000867bf86dd3ed3be157e72 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 15:04:43 +0200 Subject: [PATCH 153/159] GenerateRoot now does not inherit from OfferTree --- certora/helpers/GenerateRoot.sol | 12 +++++------ certora/helpers/OfferTree.sol | 4 ---- test/OfferTreeTest.sol | 37 ++++++++++++++++++-------------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/certora/helpers/GenerateRoot.sol b/certora/helpers/GenerateRoot.sol index 7e8efd774..ce9cb17d6 100644 --- a/certora/helpers/GenerateRoot.sol +++ b/certora/helpers/GenerateRoot.sol @@ -2,24 +2,24 @@ // Copyright (c) 2025 Morpho Association pragma solidity ^0.8.0; -import {OfferTree} from "./OfferTree.sol"; import {Offer} from "../../src/interfaces/IMidnight.sol"; +import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; -contract GenerateRoot is OfferTree { - // Build a perfect tree from a non-empty power-of-two list. Duplicate hashes share nodes. - function generateRoot(Offer[] memory leaves) public returns (bytes32) { +contract GenerateRoot { + // Reference root for a non-empty, power-of-two list of offers. + function generateRoot(Offer[] memory leaves) public pure returns (bytes32) { require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); bytes32[] memory level = new bytes32[](leaves.length); for (uint256 i = 0; i < leaves.length; i++) { - level[i] = newLeaf(leaves[i]); + level[i] = HashLib.hashOffer(leaves[i]); } uint256 levelLength = level.length; while (levelLength > 1) { levelLength /= 2; for (uint256 i = 0; i < levelLength; i++) { - level[i] = newInternalNode(level[2 * i], level[2 * i + 1]); + level[i] = HashLib.hashNode(level[2 * i], level[2 * i + 1]); } } diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 714a2826c..5fd076860 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -85,10 +85,6 @@ contract OfferTree { return isEmpty(tree[id]); } - function getHash(bytes32 id) public view returns (bytes32) { - return tree[id].hash; - } - function isLeafNode(bytes32 id) public view returns (bool) { return tree[id].left == 0 && tree[id].right == 0 && tree[id].hash != 0; } diff --git a/test/OfferTreeTest.sol b/test/OfferTreeTest.sol index 4890e4782..eb8f3d647 100644 --- a/test/OfferTreeTest.sol +++ b/test/OfferTreeTest.sol @@ -4,17 +4,20 @@ pragma solidity ^0.8.0; import {Test} from "../lib/forge-std/src/Test.sol"; import {GenerateRoot} from "../certora/helpers/GenerateRoot.sol"; +import {OfferTree} from "../certora/helpers/OfferTree.sol"; import {Offer} from "../src/interfaces/IMidnight.sol"; import {HashLib} from "../src/ratifiers/libraries/HashLib.sol"; contract OfferTreeTest is Test { - GenerateRoot internal tree; + OfferTree internal tree; + GenerateRoot internal rootReference; function setUp() public { - tree = new GenerateRoot(); + tree = new OfferTree(); + rootReference = new GenerateRoot(); } - function testGenerateRootWithPrebuiltSubtree(uint256 leftTick, uint256 rightTick) public { + function testGenerateRootMatchesOfferTree(uint256 leftTick, uint256 rightTick) public { Offer memory leftOffer; leftOffer.tick = leftTick; Offer memory rightOffer; @@ -24,14 +27,14 @@ contract OfferTreeTest is Test { assertEq(tree.newLeaf(leftOffer), left); assertEq(tree.newLeaf(rightOffer), right); assertEq(tree.newLeaf(leftOffer), left); - assertEq(tree.getHash(left), left); + assertFalse(tree.isEmpty(left)); assertTrue(tree.isLeafNode(left)); assertTrue(tree.isWellFormed(left)); bytes32 parent = tree.newInternalNode(left, right); assertEq(parent, keccak256(abi.encode(left, right))); assertEq(tree.newInternalNode(left, right), parent); - assertEq(tree.getHash(parent), parent); + assertFalse(tree.isEmpty(parent)); assertTrue(tree.isWellFormed(parent)); Offer[] memory offers = new Offer[](4); @@ -39,9 +42,11 @@ contract OfferTreeTest is Test { offers[1] = rightOffer; offers[2] = leftOffer; offers[3] = rightOffer; - bytes32 root = tree.generateRoot(offers); + bytes32 root = rootReference.generateRoot(offers); assertEq(root, keccak256(abi.encode(parent, parent))); - assertEq(tree.getHash(root), root); + assertTrue(tree.isEmpty(root)); + assertEq(tree.newInternalNode(parent, parent), root); + assertFalse(tree.isEmpty(root)); assertTrue(tree.isWellFormed(root)); bytes32[] memory proof = new bytes32[](2); @@ -50,21 +55,20 @@ contract OfferTreeTest is Test { proof[0] = i % 2 == 0 ? right : left; assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); } - assertEq(tree.generateRoot(offers), root); + assertEq(rootReference.generateRoot(offers), root); } - function testGenerateRootWithDuplicateSiblings() public { + function testGenerateRootWithDuplicateSiblings() public view { Offer[] memory offers = new Offer[](4); bytes32 leaf = HashLib.hashOffer(offers[0]); bytes32 parent = keccak256(abi.encode(leaf, leaf)); bytes32 expectedRoot = keccak256(abi.encode(parent, parent)); - assertEq(tree.generateRoot(offers), expectedRoot); - assertEq(tree.getHash(parent), parent); - assertEq(tree.getHash(expectedRoot), expectedRoot); - assertTrue(tree.isWellFormed(parent)); - assertTrue(tree.isWellFormed(expectedRoot)); - assertEq(tree.generateRoot(offers), expectedRoot); + assertEq(rootReference.generateRoot(offers), expectedRoot); + assertTrue(tree.isEmpty(leaf)); + assertTrue(tree.isEmpty(parent)); + assertTrue(tree.isEmpty(expectedRoot)); + assertEq(rootReference.generateRoot(offers), expectedRoot); } function testNewInternalNodeRequiresPopulatedChildren() public { @@ -78,6 +82,7 @@ contract OfferTreeTest is Test { tree.newInternalNode(leaf, bytes32(0)); bytes32 parent = tree.newInternalNode(leaf, leaf); - assertEq(tree.getHash(parent), parent); + assertFalse(tree.isEmpty(parent)); + assertTrue(tree.isWellFormed(parent)); } } From cd9458a6078b114f9162fa707c6ec871775f0598 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 15:14:29 +0200 Subject: [PATCH 154/159] duplicate lead test added --- test/OfferTreeTest.sol | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/OfferTreeTest.sol b/test/OfferTreeTest.sol index eb8f3d647..84fb8168e 100644 --- a/test/OfferTreeTest.sol +++ b/test/OfferTreeTest.sol @@ -58,16 +58,38 @@ contract OfferTreeTest is Test { assertEq(rootReference.generateRoot(offers), root); } + function testGenerateRootWithDuplicatePair() public view { + Offer[] memory offers = new Offer[](2); + bytes32 leaf = HashLib.hashOffer(offers[0]); + bytes32 expectedRoot = keccak256(abi.encode(leaf, leaf)); + bytes32 root = rootReference.generateRoot(offers); + assertEq(root, expectedRoot); + + bytes32[] memory proof = new bytes32[](1); + proof[0] = leaf; + for (uint256 i = 0; i < offers.length; i++) { + assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + } + } + function testGenerateRootWithDuplicateSiblings() public view { Offer[] memory offers = new Offer[](4); bytes32 leaf = HashLib.hashOffer(offers[0]); bytes32 parent = keccak256(abi.encode(leaf, leaf)); bytes32 expectedRoot = keccak256(abi.encode(parent, parent)); - assertEq(rootReference.generateRoot(offers), expectedRoot); + bytes32 root = rootReference.generateRoot(offers); + assertEq(root, expectedRoot); assertTrue(tree.isEmpty(leaf)); assertTrue(tree.isEmpty(parent)); assertTrue(tree.isEmpty(expectedRoot)); + + bytes32[] memory proof = new bytes32[](2); + proof[0] = leaf; + proof[1] = parent; + for (uint256 i = 0; i < offers.length; i++) { + assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + } assertEq(rootReference.generateRoot(offers), expectedRoot); } From bee5afa78f8254265c4b2666fb9790c253b73e90 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Fri, 18 Sep 2026 15:48:23 +0200 Subject: [PATCH 155/159] Disable caching for OfferTree verification --- certora/confs/OfferTreeWellFormed.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf index 91dd53cdf..d7a6d4930 100644 --- a/certora/confs/OfferTreeWellFormed.conf +++ b/certora/confs/OfferTreeWellFormed.conf @@ -11,6 +11,7 @@ "loop_iter": 3, "optimistic_hashing": true, "hashing_length_bound": 1024, + "disable_auto_cache_key_gen": true, "prover_args": [ "-splitParallel true", "-s [z3:def{randomSeed=1},z3:def{randomSeed=2},z3:def{randomSeed=3},z3:def{randomSeed=4},z3:def{randomSeed=5}]" From 810416739e78da36885032e43b9f1de38f8d540c Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 21 Sep 2026 10:30:33 +0200 Subject: [PATCH 156/159] all fields zero in isEmpty --- certora/helpers/OfferTree.sol | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 5fd076860..8bbd9133a 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -125,10 +125,17 @@ contract OfferTree { ); } - // Populated nodes have their hash as identifier and hash their leaf data or their two non-empty children. + // Empty nodes are fully zeroed. Populated nodes have their hash as identifier and hash their leaf data or their + // two non-empty children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; - if (isEmpty(n)) return n.left == 0 && n.right == 0; + if (isEmpty(n)) { + Leaf storage l = n.leaf; + return n.left == 0 && n.right == 0 && l.marketHash == 0 && !l.buy && l.maker == address(0) && l.start == 0 + && l.expiry == 0 && l.tick == 0 && l.group == 0 && l.callback == address(0) && l.callbackDataHash == 0 + && l.receiverIfMakerIsSeller == address(0) && l.ratifier == address(0) && !l.reduceOnly + && l.maxUnits == 0 && l.maxAssets == 0 && l.continuousFeeCap == 0; + } if (n.left == 0 && n.right == 0) { bytes32 expected = hashLeaf(n.leaf); return n.hash == expected && id == expected; From 4b669c0adeb733aa92ad2e365e0a001bd95a9122 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 21 Sep 2026 10:55:02 +0200 Subject: [PATCH 157/159] use newLeaf and newInternalNode in generateRoot; don't inherit OffertTree --- certora/confs/OfferTreeMembership.conf | 8 ++- certora/confs/OfferTreeWellFormed.conf | 8 ++- certora/helpers/GenerateRoot.sol | 16 +++-- certora/specs/OfferTreeMembership.spec | 42 +++++++++++ certora/specs/OfferTreeWellFormed.spec | 3 +- test/OfferTreeTest.sol | 96 ++++++++++++++++++++++---- 6 files changed, 148 insertions(+), 25 deletions(-) diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index c5511a2ae..3aaba0860 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -1,14 +1,18 @@ { "files": [ - "certora/helpers/OfferTree.sol" + "certora/helpers/OfferTree.sol", + "certora/helpers/GenerateRoot.sol" ], "verify": "OfferTree:certora/specs/OfferTreeMembership.spec", + "link": [ + "GenerateRoot:offerTree=OfferTree" + ], "solc": "solc-0.8.34", "solc_via_ir": true, "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, - "loop_iter": 3, + "loop_iter": 4, "optimistic_hashing": true, "hashing_length_bound": 1024, "prover_args": [ diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf index d7a6d4930..b5811801a 100644 --- a/certora/confs/OfferTreeWellFormed.conf +++ b/certora/confs/OfferTreeWellFormed.conf @@ -1,14 +1,18 @@ { "files": [ - "certora/helpers/OfferTree.sol" + "certora/helpers/OfferTree.sol", + "certora/helpers/GenerateRoot.sol" ], "verify": "OfferTree:certora/specs/OfferTreeWellFormed.spec", + "link": [ + "GenerateRoot:offerTree=OfferTree" + ], "solc": "solc-0.8.34", "solc_via_ir": true, "solc_optimize": "200", "solc_evm_version": "osaka", "optimistic_loop": true, - "loop_iter": 3, + "loop_iter": 4, "optimistic_hashing": true, "hashing_length_bound": 1024, "disable_auto_cache_key_gen": true, diff --git a/certora/helpers/GenerateRoot.sol b/certora/helpers/GenerateRoot.sol index ce9cb17d6..e6ebdd4c5 100644 --- a/certora/helpers/GenerateRoot.sol +++ b/certora/helpers/GenerateRoot.sol @@ -3,23 +3,29 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; -import {HashLib} from "../../src/ratifiers/libraries/HashLib.sol"; +import {OfferTree} from "./OfferTree.sol"; contract GenerateRoot { - // Reference root for a non-empty, power-of-two list of offers. - function generateRoot(Offer[] memory leaves) public pure returns (bytes32) { + OfferTree public immutable offerTree; + + constructor(OfferTree _offerTree) { + offerTree = _offerTree; + } + + // Populate the supplied model and return the root for a non-empty, power-of-two list of offers. + function generateRoot(Offer[] memory leaves) public returns (bytes32) { require(leaves.length > 0 && (leaves.length & (leaves.length - 1)) == 0, "invalid leaves length"); bytes32[] memory level = new bytes32[](leaves.length); for (uint256 i = 0; i < leaves.length; i++) { - level[i] = HashLib.hashOffer(leaves[i]); + level[i] = offerTree.newLeaf(leaves[i]); } uint256 levelLength = level.length; while (levelLength > 1) { levelLength /= 2; for (uint256 i = 0; i < levelLength; i++) { - level[i] = HashLib.hashNode(level[2 * i], level[2 * i + 1]); + level[i] = offerTree.newInternalNode(level[2 * i], level[2 * i + 1]); } } diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index 135ed5518..f0cfb951c 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-or-later +using GenerateRoot as generator; + methods { function isEmpty(bytes32) external returns (bool) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; + function generator.generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; function isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; function isLeafNode(bytes32) external returns (bool) envfree; + function isWellFormed(bytes32) external returns (bool) envfree; function wellFormedPath(bytes32, uint256, uint256) external returns (bool) envfree; } @@ -17,3 +21,41 @@ rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, assert isLeafNode(leafId); } + +// The constructor leaves every model entry at its default value. +definition emptyNode(bytes32 id) returns bool = currentContract.tree[id].hash == to_bytes32(0) && currentContract.tree[id].left == to_bytes32(0) && currentContract.tree[id].right == to_bytes32(0) && currentContract.tree[id].leaf.marketHash == to_bytes32(0) && !currentContract.tree[id].leaf.buy && currentContract.tree[id].leaf.maker == 0 && currentContract.tree[id].leaf.start == 0 && currentContract.tree[id].leaf.expiry == 0 && currentContract.tree[id].leaf.tick == 0 && currentContract.tree[id].leaf.group == to_bytes32(0) && currentContract.tree[id].leaf.callback == 0 && currentContract.tree[id].leaf.callbackDataHash == to_bytes32(0) && currentContract.tree[id].leaf.receiverIfMakerIsSeller == 0 && currentContract.tree[id].leaf.ratifier == 0 && !currentContract.tree[id].leaf.reduceOnly && currentContract.tree[id].leaf.maxUnits == 0 && currentContract.tree[id].leaf.maxAssets == 0 && currentContract.tree[id].leaf.continuousFeeCap == 0; + +// Check the generator itself, without assuming that its returned root or path is well-formed. +// This covers 1, 2, or 4 input offers and proofs of at most 4 siblings. Solidity loops (including +// collateral hashing) remain subject to loop_iter = 4 and the configured hash assumptions. +rule generatedRootMembershipSoundness(OfferTree.Offer[] offers, OfferTree.Offer offer, uint256 leafIndex, bytes32[] proof) { + require offers.length == 1 || offers.length == 2 || offers.length == 4; + require proof.length <= 4; + require forall bytes32 id. emptyNode(id), "start from an empty model"; + + bytes32 root = generator.generateRoot(offers); + assert !isEmpty(root), "the generator returns a populated node"; + assert isWellFormed(root), "the generated root is well-formed"; + + bytes32 leafId = hashOffer(offer); + bool inFirst = leafId == hashOffer(offers[0]); + bool inSecond = false; + bool inSecondPair = false; + if (offers.length >= 2) { + inSecond = leafId == hashOffer(offers[1]); + } + if (offers.length == 4) { + bytes32 third = hashOffer(offers[2]); + bytes32 fourth = hashOffer(offers[3]); + inSecondPair = leafId == third || leafId == fourth; + } + + require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; + assert isLeafNode(leafId), "the verified hash is a leaf in the generated model"; + assert inFirst || inSecond || inSecondPair, "the verified offer hash belongs to the generator input"; + + // Ensure the loop bounds and preconditions admit valid proofs for every supported input size. + satisfy offers.length == 1; + satisfy offers.length == 2; + satisfy offers.length == 4; +} diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 1ac844331..45198c353 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -11,7 +11,8 @@ methods { strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); -// Every node remains well-formed. +// Every node remains well-formed, including after calls from the linked GenerateRoot contract. +// Generator executions and other Solidity loops are bounded by the config's loop_iter. strong invariant wellFormed(bytes32 id) isWellFormed(id) { diff --git a/test/OfferTreeTest.sol b/test/OfferTreeTest.sol index 84fb8168e..1a160790f 100644 --- a/test/OfferTreeTest.sol +++ b/test/OfferTreeTest.sol @@ -10,11 +10,11 @@ import {HashLib} from "../src/ratifiers/libraries/HashLib.sol"; contract OfferTreeTest is Test { OfferTree internal tree; - GenerateRoot internal rootReference; + GenerateRoot internal generator; function setUp() public { tree = new OfferTree(); - rootReference = new GenerateRoot(); + generator = new GenerateRoot(tree); } function testGenerateRootMatchesOfferTree(uint256 leftTick, uint256 rightTick) public { @@ -42,55 +42,121 @@ contract OfferTreeTest is Test { offers[1] = rightOffer; offers[2] = leftOffer; offers[3] = rightOffer; - bytes32 root = rootReference.generateRoot(offers); - assertEq(root, keccak256(abi.encode(parent, parent))); - assertTrue(tree.isEmpty(root)); - assertEq(tree.newInternalNode(parent, parent), root); + bytes32 expectedRoot = keccak256(abi.encode(parent, parent)); + assertTrue(tree.isEmpty(expectedRoot)); + bytes32 root = generator.generateRoot(offers); + assertEq(root, expectedRoot); + assertTrue(tree.isLeafNode(left)); + assertTrue(tree.isLeafNode(right)); + assertTrue(tree.isWellFormed(left)); + assertTrue(tree.isWellFormed(right)); + assertTrue(tree.isWellFormed(parent)); assertFalse(tree.isEmpty(root)); assertTrue(tree.isWellFormed(root)); + assertEq(tree.newInternalNode(parent, parent), root); bytes32[] memory proof = new bytes32[](2); proof[1] = parent; for (uint256 i = 0; i < offers.length; i++) { proof[0] = i % 2 == 0 ? right : left; assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + assertTrue(tree.wellFormedPath(root, i, proof.length)); } - assertEq(rootReference.generateRoot(offers), root); + assertEq(generator.generateRoot(offers), root); + assertTrue(tree.isWellFormed(root)); } - function testGenerateRootWithDuplicatePair() public view { + function testGenerateRootWithDuplicatePair() public { Offer[] memory offers = new Offer[](2); bytes32 leaf = HashLib.hashOffer(offers[0]); bytes32 expectedRoot = keccak256(abi.encode(leaf, leaf)); - bytes32 root = rootReference.generateRoot(offers); + bytes32 root = generator.generateRoot(offers); assertEq(root, expectedRoot); + assertTrue(tree.isLeafNode(leaf)); + assertFalse(tree.isEmpty(root)); + assertTrue(tree.isWellFormed(root)); bytes32[] memory proof = new bytes32[](1); proof[0] = leaf; for (uint256 i = 0; i < offers.length; i++) { assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + assertTrue(tree.wellFormedPath(root, i, proof.length)); } + assertEq(generator.generateRoot(offers), root); } - function testGenerateRootWithDuplicateSiblings() public view { + function testGenerateRootWithDuplicateSiblings() public { Offer[] memory offers = new Offer[](4); bytes32 leaf = HashLib.hashOffer(offers[0]); bytes32 parent = keccak256(abi.encode(leaf, leaf)); bytes32 expectedRoot = keccak256(abi.encode(parent, parent)); - bytes32 root = rootReference.generateRoot(offers); + bytes32 root = generator.generateRoot(offers); assertEq(root, expectedRoot); - assertTrue(tree.isEmpty(leaf)); - assertTrue(tree.isEmpty(parent)); - assertTrue(tree.isEmpty(expectedRoot)); + assertTrue(tree.isLeafNode(leaf)); + assertTrue(tree.isWellFormed(leaf)); + assertFalse(tree.isEmpty(parent)); + assertTrue(tree.isWellFormed(parent)); + assertFalse(tree.isEmpty(root)); + assertTrue(tree.isWellFormed(root)); bytes32[] memory proof = new bytes32[](2); proof[0] = leaf; proof[1] = parent; for (uint256 i = 0; i < offers.length; i++) { assertTrue(HashLib.isLeaf(root, HashLib.hashOffer(offers[i]), i, proof)); + assertTrue(tree.wellFormedPath(root, i, proof.length)); + } + assertEq(generator.generateRoot(offers), expectedRoot); + } + + function testGenerateRootWithSingleLeaf() public { + Offer[] memory offers = new Offer[](1); + bytes32 leaf = HashLib.hashOffer(offers[0]); + bytes32 root = generator.generateRoot(offers); + assertEq(root, leaf); + assertTrue(tree.isLeafNode(root)); + assertTrue(tree.isWellFormed(root)); + assertTrue(HashLib.isLeaf(root, leaf, 0, new bytes32[](0))); + assertEq(generator.generateRoot(offers), root); + } + + function testGenerateRootRejectsInvalidLengths() public { + vm.expectRevert("invalid leaves length"); + generator.generateRoot(new Offer[](0)); + vm.expectRevert("invalid leaves length"); + generator.generateRoot(new Offer[](3)); + } + + function testGenerateRootOnlyPopulatesConfiguredTree() public { + OfferTree otherTree = new OfferTree(); + Offer[] memory offers = new Offer[](2); + bytes32 leaf = HashLib.hashOffer(offers[0]); + + bytes32 root = generator.generateRoot(offers); + + assertEq(address(generator.offerTree()), address(tree)); + assertTrue(tree.isLeafNode(leaf)); + assertFalse(tree.isEmpty(root)); + assertTrue(otherTree.isEmpty(leaf)); + assertTrue(otherTree.isEmpty(root)); + } + + function testGeneratedRootExcludesPreviouslyStoredLeaf() public { + Offer memory unrelatedOffer; + unrelatedOffer.tick = 1; + bytes32 unrelatedLeaf = tree.newLeaf(unrelatedOffer); + Offer[] memory offers = new Offer[](2); + bytes32 leaf = HashLib.hashOffer(offers[0]); + bytes32 root = generator.generateRoot(offers); + bytes32[] memory proof = new bytes32[](1); + proof[0] = leaf; + + assertTrue(tree.isLeafNode(unrelatedLeaf)); + for (uint256 i = 0; i < offers.length; i++) { + assertTrue(HashLib.isLeaf(root, leaf, i, proof)); + assertFalse(HashLib.isLeaf(root, unrelatedLeaf, i, proof)); } - assertEq(rootReference.generateRoot(offers), expectedRoot); } function testNewInternalNodeRequiresPopulatedChildren() public { From 36c3a5b92874ff37c6cd77e4cc0730367bb0b5a5 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 21 Sep 2026 13:45:39 +0200 Subject: [PATCH 158/159] remove testGenerateRootOnlyPopulatesConfiguredTree --- certora/confs/OfferTreeMembership.conf | 6 +--- certora/helpers/OfferTree.sol | 6 ++-- certora/specs/OfferTreeMembership.spec | 42 -------------------------- certora/specs/OfferTreeWellFormed.spec | 3 +- test/OfferTreeTest.sol | 27 ----------------- 5 files changed, 4 insertions(+), 80 deletions(-) diff --git a/certora/confs/OfferTreeMembership.conf b/certora/confs/OfferTreeMembership.conf index 3aaba0860..b964aa9dc 100644 --- a/certora/confs/OfferTreeMembership.conf +++ b/certora/confs/OfferTreeMembership.conf @@ -1,12 +1,8 @@ { "files": [ - "certora/helpers/OfferTree.sol", - "certora/helpers/GenerateRoot.sol" + "certora/helpers/OfferTree.sol" ], "verify": "OfferTree:certora/specs/OfferTreeMembership.spec", - "link": [ - "GenerateRoot:offerTree=OfferTree" - ], "solc": "solc-0.8.34", "solc_via_ir": true, "solc_optimize": "200", diff --git a/certora/helpers/OfferTree.sol b/certora/helpers/OfferTree.sol index 8bbd9133a..8b72af7d0 100644 --- a/certora/helpers/OfferTree.sol +++ b/certora/helpers/OfferTree.sol @@ -5,8 +5,7 @@ pragma solidity ^0.8.0; import {Offer} from "../../src/interfaces/IMidnight.sol"; import {HashLib, OFFER_TYPEHASH} from "../../src/ratifiers/libraries/HashLib.sol"; -// Fixed-size pre-image of HashLib.hashOffer. Dynamic fields are stored as hashes so CVL can re-hash a leaf -// without iterating over dynamic data. +// Fixed-size pre-image of HashLib.hashOffer. Dynamic fields are stored as hashes so CVL can re-hash a leaf without iterating over dynamic data. struct Leaf { bytes32 marketHash; // = HashLib.hashMarket(offer.market) bool buy; @@ -125,8 +124,7 @@ contract OfferTree { ); } - // Empty nodes are fully zeroed. Populated nodes have their hash as identifier and hash their leaf data or their - // two non-empty children. + // Empty nodes are fully zeroed. Populated nodes have their hash as identifier and hash their leaf data or their two non-empty children. function isWellFormed(bytes32 id) public view returns (bool) { Node storage n = tree[id]; if (isEmpty(n)) { diff --git a/certora/specs/OfferTreeMembership.spec b/certora/specs/OfferTreeMembership.spec index f0cfb951c..135ed5518 100644 --- a/certora/specs/OfferTreeMembership.spec +++ b/certora/specs/OfferTreeMembership.spec @@ -1,14 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -using GenerateRoot as generator; - methods { function isEmpty(bytes32) external returns (bool) envfree; function hashOffer(OfferTree.Offer) external returns (bytes32) envfree; - function generator.generateRoot(OfferTree.Offer[]) external returns (bytes32) envfree; function isLeaf(bytes32, bytes32, uint256, bytes32[]) external returns (bool) envfree; function isLeafNode(bytes32) external returns (bool) envfree; - function isWellFormed(bytes32) external returns (bool) envfree; function wellFormedPath(bytes32, uint256, uint256) external returns (bool) envfree; } @@ -21,41 +17,3 @@ rule membershipSoundness(OfferTree.Offer offer, bytes32 root, uint256 leafIndex, assert isLeafNode(leafId); } - -// The constructor leaves every model entry at its default value. -definition emptyNode(bytes32 id) returns bool = currentContract.tree[id].hash == to_bytes32(0) && currentContract.tree[id].left == to_bytes32(0) && currentContract.tree[id].right == to_bytes32(0) && currentContract.tree[id].leaf.marketHash == to_bytes32(0) && !currentContract.tree[id].leaf.buy && currentContract.tree[id].leaf.maker == 0 && currentContract.tree[id].leaf.start == 0 && currentContract.tree[id].leaf.expiry == 0 && currentContract.tree[id].leaf.tick == 0 && currentContract.tree[id].leaf.group == to_bytes32(0) && currentContract.tree[id].leaf.callback == 0 && currentContract.tree[id].leaf.callbackDataHash == to_bytes32(0) && currentContract.tree[id].leaf.receiverIfMakerIsSeller == 0 && currentContract.tree[id].leaf.ratifier == 0 && !currentContract.tree[id].leaf.reduceOnly && currentContract.tree[id].leaf.maxUnits == 0 && currentContract.tree[id].leaf.maxAssets == 0 && currentContract.tree[id].leaf.continuousFeeCap == 0; - -// Check the generator itself, without assuming that its returned root or path is well-formed. -// This covers 1, 2, or 4 input offers and proofs of at most 4 siblings. Solidity loops (including -// collateral hashing) remain subject to loop_iter = 4 and the configured hash assumptions. -rule generatedRootMembershipSoundness(OfferTree.Offer[] offers, OfferTree.Offer offer, uint256 leafIndex, bytes32[] proof) { - require offers.length == 1 || offers.length == 2 || offers.length == 4; - require proof.length <= 4; - require forall bytes32 id. emptyNode(id), "start from an empty model"; - - bytes32 root = generator.generateRoot(offers); - assert !isEmpty(root), "the generator returns a populated node"; - assert isWellFormed(root), "the generated root is well-formed"; - - bytes32 leafId = hashOffer(offer); - bool inFirst = leafId == hashOffer(offers[0]); - bool inSecond = false; - bool inSecondPair = false; - if (offers.length >= 2) { - inSecond = leafId == hashOffer(offers[1]); - } - if (offers.length == 4) { - bytes32 third = hashOffer(offers[2]); - bytes32 fourth = hashOffer(offers[3]); - inSecondPair = leafId == third || leafId == fourth; - } - - require isLeaf(root, leafId, leafIndex, proof), "Merkle proof verifies the offer"; - assert isLeafNode(leafId), "the verified hash is a leaf in the generated model"; - assert inFirst || inSecond || inSecondPair, "the verified offer hash belongs to the generator input"; - - // Ensure the loop bounds and preconditions admit valid proofs for every supported input size. - satisfy offers.length == 1; - satisfy offers.length == 2; - satisfy offers.length == 4; -} diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 45198c353..079e68426 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -11,8 +11,7 @@ methods { strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); -// Every node remains well-formed, including after calls from the linked GenerateRoot contract. -// Generator executions and other Solidity loops are bounded by the config's loop_iter. +// Every node stays well-formed, including after linked GenerateRoot calls, within the configured Solidity loop bounds. strong invariant wellFormed(bytes32 id) isWellFormed(id) { diff --git a/test/OfferTreeTest.sol b/test/OfferTreeTest.sol index 1a160790f..d2ca10ba5 100644 --- a/test/OfferTreeTest.sol +++ b/test/OfferTreeTest.sol @@ -29,13 +29,11 @@ contract OfferTreeTest is Test { assertEq(tree.newLeaf(leftOffer), left); assertFalse(tree.isEmpty(left)); assertTrue(tree.isLeafNode(left)); - assertTrue(tree.isWellFormed(left)); bytes32 parent = tree.newInternalNode(left, right); assertEq(parent, keccak256(abi.encode(left, right))); assertEq(tree.newInternalNode(left, right), parent); assertFalse(tree.isEmpty(parent)); - assertTrue(tree.isWellFormed(parent)); Offer[] memory offers = new Offer[](4); offers[0] = leftOffer; @@ -48,11 +46,7 @@ contract OfferTreeTest is Test { assertEq(root, expectedRoot); assertTrue(tree.isLeafNode(left)); assertTrue(tree.isLeafNode(right)); - assertTrue(tree.isWellFormed(left)); - assertTrue(tree.isWellFormed(right)); - assertTrue(tree.isWellFormed(parent)); assertFalse(tree.isEmpty(root)); - assertTrue(tree.isWellFormed(root)); assertEq(tree.newInternalNode(parent, parent), root); bytes32[] memory proof = new bytes32[](2); @@ -63,7 +57,6 @@ contract OfferTreeTest is Test { assertTrue(tree.wellFormedPath(root, i, proof.length)); } assertEq(generator.generateRoot(offers), root); - assertTrue(tree.isWellFormed(root)); } function testGenerateRootWithDuplicatePair() public { @@ -74,7 +67,6 @@ contract OfferTreeTest is Test { assertEq(root, expectedRoot); assertTrue(tree.isLeafNode(leaf)); assertFalse(tree.isEmpty(root)); - assertTrue(tree.isWellFormed(root)); bytes32[] memory proof = new bytes32[](1); proof[0] = leaf; @@ -94,11 +86,8 @@ contract OfferTreeTest is Test { bytes32 root = generator.generateRoot(offers); assertEq(root, expectedRoot); assertTrue(tree.isLeafNode(leaf)); - assertTrue(tree.isWellFormed(leaf)); assertFalse(tree.isEmpty(parent)); - assertTrue(tree.isWellFormed(parent)); assertFalse(tree.isEmpty(root)); - assertTrue(tree.isWellFormed(root)); bytes32[] memory proof = new bytes32[](2); proof[0] = leaf; @@ -116,7 +105,6 @@ contract OfferTreeTest is Test { bytes32 root = generator.generateRoot(offers); assertEq(root, leaf); assertTrue(tree.isLeafNode(root)); - assertTrue(tree.isWellFormed(root)); assertTrue(HashLib.isLeaf(root, leaf, 0, new bytes32[](0))); assertEq(generator.generateRoot(offers), root); } @@ -128,20 +116,6 @@ contract OfferTreeTest is Test { generator.generateRoot(new Offer[](3)); } - function testGenerateRootOnlyPopulatesConfiguredTree() public { - OfferTree otherTree = new OfferTree(); - Offer[] memory offers = new Offer[](2); - bytes32 leaf = HashLib.hashOffer(offers[0]); - - bytes32 root = generator.generateRoot(offers); - - assertEq(address(generator.offerTree()), address(tree)); - assertTrue(tree.isLeafNode(leaf)); - assertFalse(tree.isEmpty(root)); - assertTrue(otherTree.isEmpty(leaf)); - assertTrue(otherTree.isEmpty(root)); - } - function testGeneratedRootExcludesPreviouslyStoredLeaf() public { Offer memory unrelatedOffer; unrelatedOffer.tick = 1; @@ -171,6 +145,5 @@ contract OfferTreeTest is Test { bytes32 parent = tree.newInternalNode(leaf, leaf); assertFalse(tree.isEmpty(parent)); - assertTrue(tree.isWellFormed(parent)); } } From 78fbdc93aa7154e31b1702b2a2f24f7198192a18 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Mon, 21 Sep 2026 15:19:39 +0200 Subject: [PATCH 159/159] removed GenerateRoot links from wellformed config --- certora/confs/OfferTreeWellFormed.conf | 6 +----- certora/specs/OfferTreeWellFormed.spec | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/certora/confs/OfferTreeWellFormed.conf b/certora/confs/OfferTreeWellFormed.conf index b5811801a..b1efeb9f6 100644 --- a/certora/confs/OfferTreeWellFormed.conf +++ b/certora/confs/OfferTreeWellFormed.conf @@ -1,12 +1,8 @@ { "files": [ - "certora/helpers/OfferTree.sol", - "certora/helpers/GenerateRoot.sol" + "certora/helpers/OfferTree.sol" ], "verify": "OfferTree:certora/specs/OfferTreeWellFormed.spec", - "link": [ - "GenerateRoot:offerTree=OfferTree" - ], "solc": "solc-0.8.34", "solc_via_ir": true, "solc_optimize": "200", diff --git a/certora/specs/OfferTreeWellFormed.spec b/certora/specs/OfferTreeWellFormed.spec index 079e68426..0029741a0 100644 --- a/certora/specs/OfferTreeWellFormed.spec +++ b/certora/specs/OfferTreeWellFormed.spec @@ -11,7 +11,7 @@ methods { strong invariant zeroIsEmpty() isEmpty(to_bytes32(0)); -// Every node stays well-formed, including after linked GenerateRoot calls, within the configured Solidity loop bounds. +// Every node stays well-formed within the configured Solidity loop bounds. strong invariant wellFormed(bytes32 id) isWellFormed(id) {

    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