Skip to content

Pareto fidelity: signed Int256 storage reads (G28), ERC-20 hop lemmas (G14), kernel-eval scope (G2) - #2469

Merged
Th0rgal merged 5 commits into
mainfrom
fix/pareto-g28-g14-g2
Oct 6, 2026
Merged

Th0rgal merged 5 commits into
mainfrom
fix/pareto-g28-g14-g2

Conversation

@Th0rgal

@Th0rgal Th0rgal commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Pareto fidelity gaps G28 / G14 / G2 (closure pareto-credit-vault-proof-closure). Consumer notes: lfglabs-dev/pareto-credit-vault-proof-closure#36 (audit/pending/v-gaps.json).

CI status: all checks green at 9422010693 (2026-10-05). Verity main's latest "Verify proofs" run (98533b7) is also green, so no pre-existing failure is being waived.

G28: signed int256 += was transcribed as an unsigned checked add

Exact semantics change. In the executable (Contract) plane, getStorage on a non-packed, non-transient Int256 storage field now binds Int256.ofUint256 word and types the local .int256. Before this change it bound the raw Uint256 word. As a result, addPanic/subPanic on that value now resolve to the signed checked instances (Core.Int256.safeAdd/safeSub, Panic 0x11 on signed overflow), not the unsigned AddPanic Uint256 with the Int256 operand coerced through Coe Int256 Uint256. Packed, transient and non-Int256 fields are unchanged. The compilation-model / Yul plane is unchanged; it already lowered these as signed.

Soundness argument. The storage word is the two's-complement encoding. Int256.ofUint256 is the identity on the 256-bit word, so writes round-trip unchanged. The only thing that changes is which arithmetic instance elaboration picks. That instance now matches the Solidity int256 semantics, which the compiler plane already emitted, so the change removes a divergence between the two planes. Before the fix the executable plane had both spurious reverts (-1 + 25) and missed overflows (maxInt256 + 1 succeeded).

Tests. In Contracts/Smoke/Arithmetic.lean (decide +kernel): applyDelta 25 from a stored -1 succeeds and stores 24; applyDelta 1 from maxInt256 panics. The existing Int256CheckedSmoke is now correct as well.

G14: ERC-20 balance read through a hop

Semantics change: none. These are additive lemmas. On main, a typed call on a linked_contracts binding already runs the token body in hopCallView/hopCall at the runtime target.
Added to Verity/Core.lean: Contract.hopCall_success_of_ne, Contract.hopCall_scoped_callee (a committed hop parks the callee's plain map/address writes under .scoped callee), Contract.hopCallView_getMapping and Contract.hopCallView_getMapping2. These are proved from the definitions with no new axioms.
Tests. Contracts/Smoke/Erc20BalanceHop.lean has a generated ERC-20 and a strategy-shaped caller. held_eq_token_entry is proved for all states. Kernel witnesses show that a transfer through the hop moves the token's balances, leaves the caller's own slot untouched, and that an overdraw reverts. Foundry property tests PropertyHopToken/PropertyHopStrategy are included.

G2: keccak / mapping-slot evaluation

Semantics change: none (test only). Since #2459, no executable accessor reaches keccak: single-key mappings use .map/.mapUint/.map2, nested/struct mappings use the symbolic .mapChain, and selectors are hashed at elaboration time.
Tests. Contracts/Smoke/HashedMappings.lean g2Run evaluates a sequence of generated bodies (setMappingN, setStructMember, getMappingN, struct members) with decide +kernel. It does not use native_decide.

Remaining assumptions

  • Relating .mapChain and .scoped storage to real EVM slots assumes keccak collision-freedom. This affects the interpretation layer only; no execution path depends on it.
  • G14 consumers still assume the token is the generated standard ERC-20 (no fee-on-transfer or rebasing). The closure-side invariant strategy reserve <= token balance is proof work in the consumer, not a Verity gap.

No sorry/admit/axiom/native_decide is added.

🤖 Generated with Claude Code

Th0rgal and others added 2 commits October 5, 2026 09:37
…-20 hop lemmas (G14)

- getStorage on an Int256 field binds an Int256 (ofUint256 of the word), so
  addPanic/subPanic on it resolve to the signed checked instance, matching the
  compilation model. Previously the word was Uint256 and Int256 operands were
  coerced, so int256 += with a negative operand panicked spuriously.
- Core: hopCall_success_of_ne, hopCall_scoped_callee, hopCallView_getMapping,
  hopCallView_getMapping2.
- Smoke: Int256 regression witnesses; Erc20BalanceHop (generated ERC-20 read
  and transfer through linked_contracts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor
\n### CI Failure Hints\n\nFailed jobs: `checks`\n\nCopy-paste local triage:\n```bash\nmake check\nlake build\nFOUNDRY_PROFILE=difftest forge test -vv\n```

Th0rgal and others added 2 commits October 5, 2026 10:08
…moke state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Th0rgal
Th0rgal marked this pull request as ready for review October 5, 2026 12:15
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-05T12:22:48.679220Z 9422010 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Th0rgal
Th0rgal merged commit 36f4bf9 into main Oct 6, 2026
16 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant