You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
High-leverage roadmap to shrink ECM surface and manual modeling
Context: Recent work (including #1971 "Reject unsupported typed interface ABI params", typed SafeERC20 helpers, keccakString/keccak lit, multi-arg intrinsics, storage layout reports #1897, typed CodeData facade #1967, transient-storage nonreentrant guards #1893, and the general ECM framework) has made significant progress on external call patterns, typed interfaces, and audit artifacts.
Child issue index (added 2026-06-12)
Every roadmap item below is now tracked by a standalone issue. This issue remains the living index/prioritization document; implementation discussion belongs in the children. Source for prioritization: the Morpho Blue/Midnight fidelity analysis (Th0rgal/morpho-verity) and verity-benchmark#32 (ERC-4337 EntryPoint), which converge on the same gaps.
However, analysis of downstream usage (e.g. patterns in morpho-midnight-verity/Midnight/Proofs/TRUST_BOUNDARIES.md, Yul unsupported manifests, mapping manifest "source faithfulness" columns, and Contract.lean specs) shows that the largest remaining clusters of custom ExternalCallModules, hand-rolled calldataload/offset math, and per-contract modeling come from gaps in first-class support for:
Highest leverage (would eliminate the biggest clusters of manual code/ECMs)
First-class dynamic/nested ABI codec (top priority)
Typed abi.encode / field projections / return encoding for structs containing dynamic arrays (CollateralParams[]), bytes, tuples, and complex memory returns (toMarket returns Market memory, Offer containing Market + bytes).
This would kill or shrink the majority of the callback ECMs (*_callback_*_dynamic_abi), ratifier, market id/store/return, and most of the scattered calldataload offset math.
It would also enable source-level keccak256(abi.encode(...)) on rich types and full multi-word (including dynamic) typed interface external calls.
Typed CREATE2 + SSTORE2 / code-as-data
Proper CodeData.store[Market] / CodeData.read[Market], plus the exact SSTORE2_PREFIX ++ abi.encode(market) preimage and runtime decode for IdLib.toId / touchMarket / toMarket.
Would collapse the entire marketIdModule / storeMarketInCodeModule / marketReturnFromCodeModule cluster (currently the largest single ECM group).
Note: Current Compiler.Modules.CodeData + ABI.Frame intentionally gates on layoutSourcesSupported (rejects dynamic fields) because SSTORE2-style code-as-data is only sound for static layouts in many cases. We need a clear path for the encode preimage + decode use cases while respecting safety.
Exact Solidity storage layout, especially packed fixed arrays inside mapping structs
Example: uint128[128] collateral inside Position[id][user]. Current model expands to 128 full Uint256 words.
This is a visible gap in supplyCollateral/withdrawCollateral + collateral loop projections.
Affects the storage layout report's "source faithfulness" for packed subfields inside mappingStruct values.
(Recent Storage: emit reviewable storage layout artifacts #1897 work added rich reports, mappingStruct/structMember, non-alias certificates, and opt-in namespaces, but packed fixed-array elements inside nested mapping structs are not yet modeled at the bit level.)
High value next
Transient storage primitives (instead of per-slot midnight_liquidation_lock_transient_* ECMs). We have tload/tstore in the EDSL + Core + synthesized nonreentrant guards (transient storage via EIP-1153), but general first-class use for arbitrary computed slots/locks is still expressed via custom ECMs in some downstreams.
Better loops + CLZ/MSB (or a source-level bitmap iterator). The collateral walk in isHealthy and liquidate is currently a forEach scan or manual; Solidity uses while (_collateralBitmap != 0) + msb + clear. This affects both fidelity and the refinement extraction for the liquidation loop trace. (CLZ is available via consumer verity_intrinsic for EIP-7939; we need first-class or verified MSB + iterator sugar.)
First-class delegatecall with storage context + bytes[] calldata iteration (or a source multicall helper) so multicall isn't a giant hand-rolled ECM with manual length/offset walking + delegatecall + returndatacopy + revert bubbling. (Low-level delegatecall exists and is tracked under notModeledProxyUpgradeability; higher-level helpers are missing.)
Supporting / nice-to-have
Memory-safe assembly surface or richer raw memory primitives (reduce mstore/calldatacopy scaffolding inside ECMs).
Library support for TickLib (the wExp approximation + tickToPrice) so tickToPriceModule can become ordinary source + proof.
Better panic payload emission (currently a small solidityPanicModule ECM).
More complete event surface (many EventsLib events are still not source-shaped emit).
Relation to prior ECM reduction work
These items subsume and amplify earlier priorities:
Source-level keccak256(abi.encode(...)) (and EIP-712) becomes feasible once the dynamic/nested ABI codec exists and can feed the general keccak256(offset, size) path (or a thin compiler-owned helper) while still surfacing the standard keccak256_memory_slice_matches_evm + layout assumptions.
Multi-word (static + dynamic) external call ABI encoding via typed interfaces is a direct subset of the dynamic/nested ABI codec work.
Configurable SafeERC20 revert strings/guards becomes easier once a general ABI codec can express custom error shapes.
Many of the ECMs in the downstream retained table (callbacks, market code-as-data, ratifier, oracle reads with complex params, liquidation locks, multicall, tick math, etc.) would move from per-contract "assumed" ECMs into compiler-supported or standard surfaces, dramatically shrinking the trust surface in --trust-report / audit artifacts.
Keep AUDIT.md, TRUST_ASSUMPTIONS.md, and AXIOMS.md synchronized with any semantic/trust/CI boundary change.
Widen the supported fragment in proofs where appropriate (SupportedSpec, ExprCore, FunctionBody, IR/Yul bridges, etc.) while keeping explicit proved/assumed/unchecked + boundary classes (abiBoundary, storageLayoutAssumption, notModeledProxyUpgradeability, etc.).
Update storage layout reports, trust reports, verification status, and the generator/check scripts.
Compiler/CompilationModel/Types.lean, ParamLoading.lean, Dispatch.lean, proof modules for dynamic shapes and returnCodeData/structMember etc.
This issue is intended as a living planning document. Feedback on scoping, exact syntax (e.g. for keccak256(abi.encode(...)) or multicall), safety considerations for dynamic CodeData, and prioritization is very welcome.
Never claim completion without evidence and passing checks.
High-leverage roadmap to shrink ECM surface and manual modeling
Context: Recent work (including #1971 "Reject unsupported typed interface ABI params", typed SafeERC20 helpers, keccakString/keccak lit, multi-arg intrinsics, storage layout reports #1897, typed CodeData facade #1967, transient-storage nonreentrant guards #1893, and the general ECM framework) has made significant progress on external call patterns, typed interfaces, and audit artifacts.
Child issue index (added 2026-06-12)
Every roadmap item below is now tracked by a standalone issue. This issue remains the living index/prioritization document; implementation discussion belongs in the children. Source for prioritization: the Morpho Blue/Midnight fidelity analysis (Th0rgal/morpho-verity) and verity-benchmark#32 (ERC-4337 EntryPoint), which converge on the same gaps.
midnight_*_callback_dynamic_abiECMs (Midnight/Contract.lean:189–959); most of the 75/214 Yul identity-gate driftmidnight_idlib_toid_market_abi_create2_preimage+ initcode-layout ECMs (Contract.lean:1313–1724)uint128[128]stored as 128 words (Contract.lean:2433)Contract.lean:1109–1274)isHealthy/liquidateContract.lean:22–95)tickToPriceModuleYul ECM (Contract.lean:97–159)solidity_panic_revert_payload(Contract.lean:1765)EventsLibemitsINITIAL_CHAIN_IDas storage slot 1024 (Contract.lean:2425)checked_*Yul drift + BlueLocalNoOverflowForaxiomsProofs/Disciplines.leanlocal axiomsLoc.slot_injdischarge via layout certificatesStorageFrame.lean:69Related external-world track (oracle/IRM trust surface): #1891 → #1963 → #1964.
However, analysis of downstream usage (e.g. patterns in morpho-midnight-verity/Midnight/Proofs/TRUST_BOUNDARIES.md, Yul unsupported manifests, mapping manifest "source faithfulness" columns, and Contract.lean specs) shows that the largest remaining clusters of custom
ExternalCallModules, hand-rolled calldataload/offset math, and per-contract modeling come from gaps in first-class support for:Highest leverage (would eliminate the biggest clusters of manual code/ECMs)
First-class dynamic/nested ABI codec (top priority)
Typed
abi.encode/ field projections / return encoding for structs containing dynamic arrays (CollateralParams[]),bytes, tuples, and complex memory returns (toMarketreturnsMarket memory,OffercontainingMarket + bytes).This would kill or shrink the majority of the callback ECMs (
*_callback_*_dynamic_abi), ratifier, market id/store/return, and most of the scattered calldataload offset math.It would also enable source-level
keccak256(abi.encode(...))on rich types and full multi-word (including dynamic) typed interface external calls.Typed CREATE2 + SSTORE2 / code-as-data
Proper
CodeData.store[Market]/CodeData.read[Market], plus the exactSSTORE2_PREFIX ++ abi.encode(market)preimage and runtime decode forIdLib.toId/touchMarket/toMarket.Would collapse the entire
marketIdModule/storeMarketInCodeModule/marketReturnFromCodeModulecluster (currently the largest single ECM group).Note: Current
Compiler.Modules.CodeData+ABI.Frameintentionally gates onlayoutSourcesSupported(rejects dynamic fields) because SSTORE2-style code-as-data is only sound for static layouts in many cases. We need a clear path for the encode preimage + decode use cases while respecting safety.Exact Solidity storage layout, especially packed fixed arrays inside mapping structs
Example:
uint128[128]collateral insidePosition[id][user]. Current model expands to 128 fullUint256words.This is a visible gap in
supplyCollateral/withdrawCollateral+ collateral loop projections.Affects the storage layout report's "source faithfulness" for packed subfields inside
mappingStructvalues.(Recent Storage: emit reviewable storage layout artifacts #1897 work added rich reports,
mappingStruct/structMember, non-alias certificates, and opt-in namespaces, but packed fixed-array elements inside nested mapping structs are not yet modeled at the bit level.)High value next
Transient storage primitives (instead of per-slot
midnight_liquidation_lock_transient_*ECMs). We havetload/tstorein the EDSL + Core + synthesized nonreentrant guards (transient storage via EIP-1153), but general first-class use for arbitrary computed slots/locks is still expressed via custom ECMs in some downstreams.Better loops + CLZ/MSB (or a source-level bitmap iterator). The collateral walk in
isHealthyandliquidateis currently aforEachscan or manual; Solidity useswhile (_collateralBitmap != 0) + msb + clear. This affects both fidelity and the refinement extraction for the liquidation loop trace. (CLZ is available via consumerverity_intrinsicfor EIP-7939; we need first-class or verified MSB + iterator sugar.)First-class delegatecall with storage context + bytes[] calldata iteration (or a source multicall helper) so multicall isn't a giant hand-rolled ECM with manual length/offset walking +
delegatecall+returndatacopy+ revert bubbling. (Low-leveldelegatecallexists and is tracked undernotModeledProxyUpgradeability; higher-level helpers are missing.)Supporting / nice-to-have
mstore/calldatacopyscaffolding inside ECMs).wExpapproximation +tickToPrice) sotickToPriceModulecan become ordinary source + proof.solidityPanicModuleECM).EventsLibevents are still not source-shapedemit).Relation to prior ECM reduction work
These items subsume and amplify earlier priorities:
keccak256(abi.encode(...))(and EIP-712) becomes feasible once the dynamic/nested ABI codec exists and can feed the generalkeccak256(offset, size)path (or a thin compiler-owned helper) while still surfacing the standardkeccak256_memory_slice_matches_evm+ layout assumptions.Many of the ECMs in the downstream retained table (callbacks, market code-as-data, ratifier, oracle reads with complex params, liquidation locks, multicall, tick math, etc.) would move from per-contract "assumed" ECMs into compiler-supported or standard surfaces, dramatically shrinking the trust surface in
--trust-report/ audit artifacts.Cross-cutting requirements (per project conventions)
AUDIT.md,TRUST_ASSUMPTIONS.md, andAXIOMS.mdsynchronized with any semantic/trust/CI boundary change.SupportedSpec,ExprCore,FunctionBody, IR/Yul bridges, etc.) while keeping explicitproved/assumed/unchecked+ boundary classes (abiBoundary,storageLayoutAssumption,notModeledProxyUpgradeability, etc.).CompilationModelFeatureTestsmokes, Foundry differentials, and end-to-end examples.EXTERNAL_CALL_MODULES.md,ROADMAP.md, EDSL reference, capabilities, production patterns, etc.).lake build,make check(including layout drift, layer boundaries, Yul identity, proof length, hygiene),make test-foundry, etc.--deny-*gates).Proposed rough phases (subject to scoping)
mappingStructvalues (report + projections).References (internal to this repo)
docs/EXTERNAL_CALL_MODULES.md(ECM architecture, CodeData facade, hashing helpers, typed interfaces)docs/ROADMAP.md,TRUST_ASSUMPTIONS.md,AUDIT.md,AXIOMS.mdCompiler/Modules/CodeData.lean,Compiler/ABI/Frame.lean(thelayoutSourcesSupportedgate)Verity/Macro/Translate/Expr.lean(typed interface call gates,abiEncode,requireTypedInterfaceStatic*)scripts/generate_storage_layout_report.py,artifacts/storage_layout_report.json,STORAGE_LAYOUT_SUMMARY.mdCompiler/CompilationModel/Types.lean,ParamLoading.lean,Dispatch.lean, proof modules for dynamic shapes andreturnCodeData/structMemberetc.This issue is intended as a living planning document. Feedback on scoping, exact syntax (e.g. for
keccak256(abi.encode(...))or multicall), safety considerations for dynamic CodeData, and prioritization is very welcome.Never claim completion without evidence and passing checks.