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
Bring the verity_contract EDSL and CompilationModel to feature parity with Solidity 0.8.x, so that any standard Solidity smart contract can be faithfully expressed, compiled, and verified through Verity's pipeline. This is not about supporting arbitrary Solidity syntax, but about ensuring every semantically meaningful Solidity pattern has a first-class Verity equivalent with correct compilation and (where applicable) formal verification.
Background
Verity's verity_contract macro currently supports a substantial subset of Solidity patterns, sufficient for standard DeFi contracts (ERC20, ERC721, governance, simple AMMs). However, several Solidity features that production contracts commonly use are either partially supported, missing, or have no proof coverage.
Current Solidity Interop Status (from ROADMAP.md, Issue #586)
Feature
Current Status
Detail
Custom errors + typed revert payloads
Partial
ABI encoding works for scalar + tuple/array/bytes payloads (direct param refs only); expression-arg composites fail fast
Low-level calls + returndata
Partial
call/staticcall/delegatecall + returndataSize/returndataCopy/revertReturndata/returndataOptionalBoolAt exist; proof coverage is zero
fallback/receive/payable modeling
Partial
isPayable flag exists on functions; no dedicated fallback/receive entrypoint support
Event ABI parity
Supported
Full indexed dynamic/tuple hashing; proof-covered
Storage layout controls
Partial
Packed fields, explicit slots, alias slots, reserved ranges, struct-valued mappings all exist; proof coverage is partial
ABI JSON generation
Partial
--abi-output emits per-contract ABI JSON; view/pure mutability markers included
String/bytes ABI support
Partial
ABI-level only; no storage-level string/bytes
Current Type System Coverage
Verity type
Solidity equivalent
Status
Uint256
uint256
Full
Int256
int256
Full
Uint8
uint8
Full
Address
address
Full
Bytes32
bytes32
Full
Bool
bool
Full
String
string
ABI-only (calldata/return/events); no storage
Bytes
bytes
ABI-only (calldata/return/events); no storage
Array T
T[]
Calldata arrays (read-only); storage dynamic arrays (dynamicArray) for uint256
Tuple [...]
Solidity tuples
ABI encoding; no first-class destructuring
—
uint8–uint248 (other widths)
Missing — only uint8 and uint256 exist
—
int8–int248 (other widths)
Missing — only int256 exists
—
bytes1–bytes31
Missing — only bytes32 exists
—
mapping(K => mapping(K2 => mapping(K3 => V)))
Partial — mapping2 is 2-deep; mappingChain is arbitrary-depth but has no proof coverage
—
struct (as storage root)
Missing — only struct-valued mappings, not top-level storage structs
—
enum
Missing — encode as uint8 manually
—
Fixed-point (ufixed/fixed)
Missing — not widely used in practice
Current CompilationModel Construct Coverage
Expressions (44 constructors in CompilationModel.Expr):
30+ constructors fully operational
Several (constructorArg, keccak256, external calls, array ops, dynamicBytesEq) operational but outside the proven fragment
Statements (31 constructors in CompilationModel.Stmt):
All 31 compile and execute correctly
~15 are in the proven fragment; ~16 are outside (events, errors, returns, calls, array mutations)
Parity Gaps — Detailed Breakdown
P0: Missing Type Widths (Blocks Many Contracts)
Solidity contracts routinely use uint128, uint64, uint32, uint16, int128, bytes4, bytes20, etc. Currently Verity only supports uint8, uint256, int256, bytes32, address, and bool.
What to add:
UintN for N ∈ {16, 32, 64, 128, 160, 224, 248} — at minimum the widths used by OpenZeppelin, Uniswap, and Morpho contracts. This requires:
ABI encoding/decoding (left-pad to 32 bytes, mask on decode)
Storage packing support (already exists via PackedBits)
Arithmetic overflow checking for safe operations
IntN for common signed widths — less common but needed for price feeds, time deltas
BytesN for N < 32 — needed for function selectors (bytes4), short identifiers
enum support — compile as bounded uint8/uint16 with range checks
P1: Storage Strings and Bytes
Currently string/bytes are ABI-only (calldata parameters, return values, events). Production contracts store strings (e.g., token name/symbol, URI storage in ERC721).
Solidity's contract A is B, C pattern is the primary code organization mechanism. Currently, Verity contracts are flat — all functions must be defined in a single verity_contract block.
What to add:
Composition model: Allow verity_contract to reference another contract's functions/storage layout as a base
Virtual/override dispatch: Model Solidity's C3 linearization for virtual function resolution
Abstract contracts: Contracts with unimplemented functions (for template patterns)
Alternative approach: Instead of full inheritance, support trait-like composition where base contract functionality is imported as a library of functions + storage layout declarations. This is simpler and arguably better for verification (explicit composition vs implicit linearization).
P3: Constructor Features
Current constructor support is basic: parameters + body. Missing:
Inheritance constructor chaining: Base constructor calls
Constructor modifiers: payable constructor (flag exists but limited)
CREATE2 / factory patterns: Constructor with salt for deterministic deployment
P4: Modifier Support
Solidity modifiers (modifier onlyOwner() { require(msg.sender == owner); _; }) are used in almost every production contract.
What to add:
Modifier declarations: Named code blocks with a _ continuation point
Modifier application: Function annotations that wrap the function body
Modifier composition: Multiple modifiers on a single function (chained execution)
Compilation: Inline modifier bodies around the function body at compile time (matching solc behavior)
Simpler alternative: Modifiers are syntactic sugar for require checks at function entry. A preconditions: [...] section in verity_contract functions could capture the same pattern without the complexity of _ continuation semantics.
P5: Advanced Control Flow
Feature
Status
What to add
if/else
Supported
—
for loops
Supported (as forEach with bound)
True for(init; cond; post) with arbitrary conditions
while loops
Missing
while(cond) { body } — desugar to for(; cond; ) { body }
Beyond Parity: Language Design Improvements (#1726)
While this issue tracks reaching Solidity feature parity, #1726 tracks going beyond parity by fixing Solidity's systemic design flaws at the language level. The beyond-parity features integrate into this issue's waves:
Goal
Bring the
verity_contractEDSL and CompilationModel to feature parity with Solidity 0.8.x, so that any standard Solidity smart contract can be faithfully expressed, compiled, and verified through Verity's pipeline. This is not about supporting arbitrary Solidity syntax, but about ensuring every semantically meaningful Solidity pattern has a first-class Verity equivalent with correct compilation and (where applicable) formal verification.Background
Verity's
verity_contractmacro currently supports a substantial subset of Solidity patterns, sufficient for standard DeFi contracts (ERC20, ERC721, governance, simple AMMs). However, several Solidity features that production contracts commonly use are either partially supported, missing, or have no proof coverage.Current Solidity Interop Status (from ROADMAP.md, Issue #586)
call/staticcall/delegatecall+returndataSize/returndataCopy/revertReturndata/returndataOptionalBoolAtexist; proof coverage is zerofallback/receive/payable modelingisPayableflag exists on functions; no dedicatedfallback/receiveentrypoint support--abi-outputemits per-contract ABI JSON; view/pure mutability markers includedCurrent Type System Coverage
Uint256uint256Int256int256Uint8uint8AddressaddressBytes32bytes32BoolboolStringstringBytesbytesArray TT[]dynamicArray) foruint256Tuple [...]uint8–uint248(other widths)uint8anduint256existint8–int248(other widths)int256existsbytes1–bytes31bytes32existsmapping(K => mapping(K2 => mapping(K3 => V)))mapping2is 2-deep;mappingChainis arbitrary-depth but has no proof coveragestruct(as storage root)enumuint8manuallyufixed/fixed)Current CompilationModel Construct Coverage
Expressions (44 constructors in
CompilationModel.Expr):constructorArg,keccak256, external calls, array ops,dynamicBytesEq) operational but outside the proven fragmentStatements (31 constructors in
CompilationModel.Stmt):Parity Gaps — Detailed Breakdown
P0: Missing Type Widths (Blocks Many Contracts)
Solidity contracts routinely use
uint128,uint64,uint32,uint16,int128,bytes4,bytes20, etc. Currently Verity only supportsuint8,uint256,int256,bytes32,address, andbool.What to add:
UintNfor N ∈ {16, 32, 64, 128, 160, 224, 248} — at minimum the widths used by OpenZeppelin, Uniswap, and Morpho contracts. This requires:ParamType.uintNconstructor (or parameterizedParamType.uint width)PackedBits)IntNfor common signed widths — less common but needed for price feeds, time deltasBytesNfor N < 32 — needed for function selectors (bytes4), short identifiersenumsupport — compile as boundeduint8/uint16with range checksP1: Storage Strings and Bytes
Currently string/bytes are ABI-only (calldata parameters, return values, events). Production contracts store strings (e.g., token name/symbol, URI storage in ERC721).
What to add:
FieldType.string/FieldType.bytesstorage fieldsExpr.storageString/Stmt.setStorageStringread/write operationsP2: Inheritance and Interface Composition
Solidity's
contract A is B, Cpattern is the primary code organization mechanism. Currently, Verity contracts are flat — all functions must be defined in a singleverity_contractblock.What to add:
verity_contractto reference another contract's functions/storage layout as a baseAlternative approach: Instead of full inheritance, support trait-like composition where base contract functionality is imported as a library of functions + storage layout declarations. This is simpler and arguably better for verification (explicit composition vs implicit linearization).
P3: Constructor Features
Current constructor support is basic: parameters + body. Missing:
immutablessection exists for scalar types); missing: complex immutable initialization, immutable arrays/structspayableconstructor (flag exists but limited)P4: Modifier Support
Solidity modifiers (
modifier onlyOwner() { require(msg.sender == owner); _; }) are used in almost every production contract.What to add:
_continuation pointsolcbehavior)Simpler alternative: Modifiers are syntactic sugar for require checks at function entry. A
preconditions: [...]section inverity_contractfunctions could capture the same pattern without the complexity of_continuation semantics.P5: Advanced Control Flow
if/elseforloopsforEachwith bound)for(init; cond; post)with arbitrary conditionswhileloopswhile(cond) { body }— desugar tofor(; cond; ) { body }do-whiledo { body } while(cond)break/continuetry/catchreturnreturnValuesexists; no destructuring assignmentExpr.iteP6: Memory and ABI Features
abi.encodeabi.encodeabi.encodePackedkeccak256(abi.encodePacked(...))patternsabi.encodeWithSelectorabi.decodetype(X).max/.minblock.prevrandaogasleft()address(this).balanceSELFBALANCEopcodemsg.sigmsg.datacalldataload)P7: Advanced Storage Patterns
mappingChainexists but no proof coverageuint256dynamic arrayststore/tload)PackedBitsdeleteP8: External Interaction Patterns
call/staticcall/delegatecalltransfer/sendcallwith 2300 gasnonReentrantdelegatecallto self with encoded calldatadelegatecall+ storage slot patterns; tracked in #1420selfdestructProposed Execution Order
Wave 1: Type System Completeness (4–6 weeks)
UintNfor common widths) — unblocks the most contractsIntN)Wave 2: Control Flow and Modifiers (3–4 weeks)
whileloops — desugar toforbreak/continue— surface in EDSL, already available at Yul level_continuation orpreconditionssugarWave 3: Storage Completeness (4–6 weeks)
deletesemantics — zero-out patternsuint256mappingChainWave 4: ABI and Memory (3–4 weeks)
abi.encode/abi.encodePacked/abi.decodeabi.encodeWithSelectortype(X).max/.minconstantsblock.prevrandao,gasleft(),address(this).balance,msg.sig)Wave 5: Composition and Inheritance (6–8 weeks)
Wave 6: Advanced Interactions (4–6 weeks)
try/catchsugar over low-level call + returndata checkdelegatecallsupport #1420)Beyond Parity: Language Design Improvements (#1726)
While this issue tracks reaching Solidity feature parity, #1726 tracks going beyond parity by fixing Solidity's systemic design flaws at the language level. The beyond-parity features integrate into this issue's waves:
typessection) — #1727match— #1727@[requires Role]with auto-theorems — #1728@[view]/@[modifies]) with auto-theorem generation — #1729Call.Resulttype withmatch+!sugar — #1727unsafeblocks — #1728Axis Sub-Issues
Call.Resulttype@[requires Role](auto-theorems),unsafeblocks@[view]/@[modifies]/@[no_external_calls]verified annotations that generate frame condition theoremsRelationship to Other Issues
Success Criteria
Minimum Viable Parity (Waves 1–3)
whileloops,break/continueavailable in EDSLverity_contractverity_contract(or documented gap list < 5 items)Full Parity (Waves 1–6)
verity_contractequivalent or a documented, justified exclusionROADMAP.mdshows "supported" for all P0–P2 itemsverity-compilerdiagnostics guide migration for any remaining unsupported patternsEstimated Effort
Waves 1 and 2 can be parallelized. Waves 3 and 4 can be parallelized.