Skip to content

[Property Coverage] Add finite address set modeling for sum properties #39

@Th0rgal

Description

@Th0rgal

Overview

Enable proving sum properties ("total supply = sum of all balances") by adding finite address set abstraction.

Status: Design clear, well-understood problem
Effort: 1-2 weeks
Difficulty: Medium (requires modeling changes)
Priority: Low (polish, not blocking core verification)
Impact: Completes Ledger contract verification to 100%

Current State

Property Coverage: 70% (203/292)

  • ✅ All testable properties are covered!
  • ❌ 7 sum properties cannot be proven

The 7 Blocked Properties:

  1. mint_sum_equation - Minting increases total by amount
  2. burn_sum_equation - Burning decreases total by amount
  3. transfer_sum_preservation - Transfers preserve total
  4. totalSupply_equals_sum - Total supply equals sum of all balances
  5. mint_increases_supply - Minting increases total supply
  6. burn_decreases_supply - Burning decreases total supply
  7. transfer_preserves_supply - Transfers don't change total supply

The Problem

Current model: Addresses are unbounded (Nat, representing uint160)

structure State where
  balances : Nat → Nat  -- Address → Balance (unbounded)
  totalSupply : Nat

Issue: Cannot sum over infinite domain

  • Cannot express "sum of all balances"
  • Properties like totalSupply = Σ balances are unprovable

Proposed Solution

Add Finite Address Set Abstraction

-- Finite set of addresses with bound
structure FiniteAddressSet where
  addresses : Finset Address
  maxSize : addresses.card ≤ 2^160  -- Bound by uint160 max

-- State with tracked addresses  
structure StateWithAddresses where
  balances : Nat → Nat
  totalSupply : Nat
  knownAddresses : FiniteAddressSet
  -- Invariant: only knownAddresses have non-zero balances
  balances_finite : ∀ addr ∉ knownAddresses.addresses, balances addr = 0

Prove Sum Properties

-- Helper: sum balances over finite set
def sum_balances (addrs : Finset Address) (balances : Address → Nat) : Nat :=
  addrs.sum (fun addr => balances addr)

-- Main invariant
theorem totalSupply_equals_sum (s : StateWithAddresses) :
    s.totalSupply = sum_balances s.knownAddresses.addresses s.balances := by
  -- Proof by induction on operations (mint, burn, transfer)
  sorry

-- Now we can prove the 7 properties!
theorem mint_preserves_supply_sum (s : StateWithAddresses) (to : Address) (amount : Nat) :
    let s' := mint s to amount
    sum_balances s'.knownAddresses.addresses s'.balances = 
      sum_balances s.knownAddresses.addresses s.balances + amount := by
  sorry

Implementation Plan

Phase 1: Modeling (Week 1)

Files to modify:

  • DumbContracts/Core.lean - Add FiniteAddressSet
  • Contract state definitions - Add knownAddresses tracking

Changes:

  1. Define FiniteAddressSet structure
  2. Add to contract states
  3. Update operations to maintain knownAddresses
  4. Prove finiteness invariant

Phase 2: Sum Properties (Week 2)

Files to modify:

  • DumbContracts/Specs/Ledger.lean - Add sum property definitions
  • DumbContracts/Specs/Ledger/Proofs.lean - Prove the 7 properties

Proofs:

  1. totalSupply_equals_sum - Base invariant
  2. mint_preserves_supply_sum - Minting adds to both
  3. burn_preserves_supply_sum - Burning subtracts from both
  4. transfer_preserves_supply_sum - Transfer doesn't change sum
  5. Derive the other 4 from these

Acceptance Criteria

  • FiniteAddressSet structure defined
  • Contract states track knownAddresses
  • All operations maintain knownAddresses invariant
  • 7 sum properties proven (no sorries)
  • Property coverage increases to ~72%+ (206/292)
  • Ledger contract at 100% completeness
  • CI passes (all tests)

Impact

Before: 70% property coverage, 7 sum properties unprovable

After: ~72% property coverage, Ledger contract 100% verified

  • ✅ All invariants provable
  • ✅ Complete verification of supply properties
  • ✅ Stronger correctness guarantees

Alternative Approaches

Option B: Bounded Address Space

Use Fin (2^160) instead of Nat for addresses.

Pros: More accurate model
Cons: More complex, may require extensive refactoring

Option C: Ghost State

Add specification-only activeAddresses that tracks non-zero balances.

Pros: Minimal changes to existing code
Cons: Less explicit, harder to reason about

Recommendation: Option A (FiniteAddressSet) - clear, explicit, maintainable

References

Questions?

This is a well-understood problem with a clear solution. The main work is updating the model and proving the properties - no research needed!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestleanLean 4 codeproofLean proof work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions