Skip to content

fix!: remediate DKG recovery and E3 program registration - #1767

Merged
ctrlc03 merged 2 commits into
mainfrom
fix/audit-remediations-28516
Aug 4, 2026
Merged

fix!: remediate DKG recovery and E3 program registration#1767
ctrlc03 merged 2 commits into
mainfrom
fix/audit-remediations-28516

Conversation

@hmzakhalid

@hmzakhalid hmzakhalid commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What

Closes #1765.

This change remediates three audit findings:

  • M-42: Fatal threshold-keyshare collector timeouts now commit KeyshareState::Failed before they publish E3Failed. EffectsEnabled redrives the saved terminal payload after startup.
  • M-43: registerE3Program now requires the Interfold owner.
  • M-39: Production deployment now requires one deployed E3 program and registers it in Interfold.initialize before ownership transfers to the Safe.

Review follow-up also makes a terminal failure payload immutable, rejects zero and no-code E3 program addresses on-chain and in deployment validation, initializes test deployments with a deployed mock program, and routes the interfold:enableE3 task through an available owner signer. The checked-in example configuration remains an intentionally incomplete template. Configuration validation rejects its zero E3 program until an operator supplies a deployed address.

The initializer ABI now includes initialE3Program. The contract adds no storage. The final Interfold runtime is 24,281 bytes, which passes the project release budget and leaves 295 bytes below EIP-170.

The tracked Hardhat artifacts were regenerated from the final Solidity sources because the initializer ABI and imported source metadata changed. They are compiler output and were not edited manually.

Checklist

  • Verified at the smallest covering scopecargo test -p e3-keyshare (34 passing); pnpm --filter @interfold/contracts test:interfold (58 passing); pnpm evm:test (568 passing, 6 pending).
  • Harness docs — updated agent/INVARIANTS.md, agent/CRATES_ARCHITECTURE.md, and the E3 request and DKG flow traces.
  • Invariantspnpm check:invariants, pnpm --filter @interfold/contracts validate:upgrade, and pnpm --filter @interfold/contracts size:check pass.
  • Known bugs table — added resolved entries for M-42, M-43, and M-39.
  • Breaking? — the commit and PR use fix!:; merge this PR only with a breaking release.

Additional gates: pnpm lint, pnpm format:check, pnpm check:docs, pnpm check:committee, pnpm check:license, pnpm check:pnpm, TypeScript compilation, and upgrade-layout validation.

Summary by CodeRabbit

  • New Features

    • Added durable handling for keyshare failures, including DKG and decryption timeouts, with replay after restart.
    • Failed operations no longer resume earlier processing phases.
    • Interfold deployments now require one deployed E3 program, registered during initialization.
    • Additional E3 program registrations are restricted to the contract owner.
  • Bug Fixes

    • Prevented repeated processing of responses after a keyshare operation has failed.
    • Added validation to reject invalid or undeployed E3 program addresses.
  • Documentation

    • Updated deployment, configuration, and protocol guidance for E3 program registration and failure recovery.

@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crisp Ready Ready Preview Aug 4, 2026 7:54pm
interfold-dashboard Ready Ready Preview Aug 4, 2026 7:54pm
interfold-docs Ready Ready Preview Aug 4, 2026 7:54pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds durable terminal failure handling for threshold keyshares and requires one deployed E3 program during Interfold initialization. Later E3 program registration is owner-only. Deployment validation, restart redrive, tests, and documentation reflect these contracts.

Changes

Durable keyshare failure recovery

Layer / File(s) Summary
Terminal failure state contract
crates/keyshare/src/threshold_keyshare/state.rs, crates/keyshare/src/threshold_keyshare/state_tests.rs
KeyshareState::Failed records the failed stage and reason. Transition rules prevent completed states and changed failure payloads from entering Failed.
Timeout failure persistence
crates/keyshare/src/threshold_keyshare/handlers.rs, agent/flow-trace/04_DKG_AND_COMPUTATION.md
Collection timeout paths persist terminal failure before publishing E3Failed and stopping the actor.
Restart failure redrive
crates/keyshare/src/threshold_keyshare/effects/*, crates/keyshare/src/threshold_keyshare/tests.rs, agent/INVARIANTS.md, agent/CRATES_ARCHITECTURE.md
Hydrated failures republish the stored E3Failed event when effects are enabled. Replayed DKG responses are ignored. Tests verify persistence and redrive.

E3 program bootstrap and governance

Layer / File(s) Summary
Initialization and owner-only registration
packages/interfold-contracts/contracts/Interfold.sol, packages/interfold-contracts/contracts/interfaces/IInterfold.sol, packages/interfold-contracts/test/Interfold.spec.ts, agent/INVARIANTS.md, agent/flow-trace/*
Interfold.initialize registers the initial E3 program before ownership transfer. Later registrations require the owner and deployed runtime code.
Deployment configuration and validation
packages/interfold-contracts/scripts/*, packages/interfold-contracts/ignition/*, packages/interfold-contracts/test/*, packages/interfold-contracts/README.md
Configuration requires exactly one deployed E3 program. Deployment passes, records, validates, and reuses that program without separate automatic registration transactions.
Regenerated contract artifacts
packages/interfold-contracts/artifacts/contracts/*
Generated artifact metadata updates compiler build identifiers without ABI or bytecode changes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Collector
  participant KeyshareRepository
  participant EventBus
  participant ThresholdKeyshare
  Collector->>KeyshareRepository: persist KeyshareState::Failed
  KeyshareRepository->>EventBus: publish E3Failed
  Collector->>ThresholdKeyshare: stop actor
  ThresholdKeyshare->>KeyshareRepository: hydrate Failed state
  ThresholdKeyshare->>EventBus: replay E3Failed after EffectsEnabled
Loading
sequenceDiagram
  participant DeploymentConfig
  participant Interfold
  participant Safe
  DeploymentConfig->>Interfold: initialize(initialE3Program)
  Interfold->>Interfold: registerE3Program(initialE3Program)
  Interfold->>Safe: transferOwnership()
  Safe->>Interfold: registerE3Program(program)
Loading

Possibly related PRs

Suggested reviewers: 0xjei

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes unrelated buildInfoId-only changes in five generated artifacts that do not support the linked audit remediations [#1765]. Revert the buildInfoId-only artifact edits, or document why regeneration requires them for this ABI change.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy durable failure redrive, owner-only registration, initial program bootstrap, validation, ABI updates, and stated storage and size constraints [#1765].
Docstring Coverage ✅ Passed Docstring coverage is 85.19% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: DKG recovery and E3 program registration remediation.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/audit-remediations-28516

Comment @coderabbitai help to get the list of available commands.

@hmzakhalid
hmzakhalid marked this pull request as ready for review August 3, 2026 23:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/interfold-contracts/contracts/Interfold.sol (2)

633-639: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Prevent undeployed E3 addresses from entering the deployment flow.

The current flow can register an address with no runtime code and then report it as enabled. The supplied zero address can therefore pass registration while E3 requests cannot call validate.

  • packages/interfold-contracts/contracts/Interfold.sol#L633-L639: reject zero and no-code addresses in registerE3Program.
  • packages/interfold-contracts/contracts/Interfold.sol#L209-L233: route initialE3Program through the same guard.
  • packages/interfold-contracts/scripts/protocol/values.ts#L183-L186: reject zero during configuration validation.
  • packages/interfold-contracts/scripts/protocol/validate.ts#L125-L130: check provider bytecode in addition to mapping membership.
  • packages/interfold-contracts/deploy/protocol/example.protocol.config.json#L77-L77: replace zero with an actual deployed E3 program address.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interfold-contracts/contracts/Interfold.sol` around lines 633 - 639,
Prevent undeployed or zero E3 addresses from entering deployment flows: update
Interfold.sol lines 633-639 in registerE3Program and lines 209-233 for
initialE3Program to apply zero-address and runtime-code checks; update
packages/interfold-contracts/scripts/protocol/values.ts lines 183-186 to reject
zero configuration values; update
packages/interfold-contracts/scripts/protocol/validate.ts lines 125-130 to
verify provider bytecode alongside mapping membership; replace the zero E3
address in
packages/interfold-contracts/deploy/protocol/example.protocol.config.json line
77 with an actual deployed E3 program address.

633-639: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Route enableE3 through the Interfold owner.

The task uses the first signer, but protocol deployment sets config.safe as the Interfold owner. Submit the call through the Safe or use an owner signer. Skip the call when e3Programs[e3Address] is already true, because deployment registers config.e3Programs[0].

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interfold-contracts/contracts/Interfold.sol` around lines 633 - 639,
The deployment flow calling registerE3Program must use the Interfold owner
configured as config.safe, submitting through the Safe or an owner signer rather
than assuming the first signer. Before invoking it, check e3Programs[e3Address]
and skip the call when already enabled, preserving the existing registration
behavior for unregistered programs.
🧹 Nitpick comments (1)
packages/interfold-contracts/test/fixtures/system.ts (1)

413-413: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Exercise initialization with a deployed E3 program.

The fixture and the initialization test use placeholder addresses. They do not verify the deployed-program requirement and register invalid addresses alongside the real mock program.

  • packages/interfold-contracts/test/fixtures/system.ts#L413-L413: deploy the mock before Interfold initialization or require a real initial program.
  • packages/interfold-contracts/test/Interfold.spec.ts#L71-L73: pass the deployed mock address instead of AddressTwo.
  • packages/interfold-contracts/test/Interfold.spec.ts#L92-L96: assert that the deployed mock address is registered.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interfold-contracts/test/fixtures/system.ts` at line 413, Update the
system fixture’s initialE3Program setup to deploy the mock E3 program before
Interfold initialization, or require a valid deployed program instead of
defaulting to ADDRESS_ONE. In
packages/interfold-contracts/test/Interfold.spec.ts lines 71-73, pass the
deployed mock address rather than AddressTwo; at lines 92-96, assert that this
deployed mock address is registered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/keyshare/src/threshold_keyshare/state.rs`:
- Around line 146-147: Update the transition logic around the `new_state` match
in the keyshare state machine to reject any transition from an existing
`K::Failed` state unless the incoming failure is exactly equal and therefore
idempotent. Ensure the earlier same-variant handling cannot permit a different
failure stage or reason, and add a test covering a second `Failed` transition
with different payloads.

In `@packages/interfold-contracts/ignition/modules/interfold.ts`:
- Around line 15-18: Require a real, bytecode-backed E3 program across all
deployment entry points: in
packages/interfold-contracts/ignition/modules/interfold.ts:15-18, remove the 0x1
default or validate the configured initialE3Program before initialization; in
packages/interfold-contracts/scripts/deployAndSave/interfold.ts:34, make
initialE3Program required; and at
packages/interfold-contracts/scripts/deployAndSave/interfold.ts:51, remove the
ADDRESS_ONE fallback and reject the address when deployed code is absent.

---

Outside diff comments:
In `@packages/interfold-contracts/contracts/Interfold.sol`:
- Around line 633-639: Prevent undeployed or zero E3 addresses from entering
deployment flows: update Interfold.sol lines 633-639 in registerE3Program and
lines 209-233 for initialE3Program to apply zero-address and runtime-code
checks; update packages/interfold-contracts/scripts/protocol/values.ts lines
183-186 to reject zero configuration values; update
packages/interfold-contracts/scripts/protocol/validate.ts lines 125-130 to
verify provider bytecode alongside mapping membership; replace the zero E3
address in
packages/interfold-contracts/deploy/protocol/example.protocol.config.json line
77 with an actual deployed E3 program address.
- Around line 633-639: The deployment flow calling registerE3Program must use
the Interfold owner configured as config.safe, submitting through the Safe or an
owner signer rather than assuming the first signer. Before invoking it, check
e3Programs[e3Address] and skip the call when already enabled, preserving the
existing registration behavior for unregistered programs.

---

Nitpick comments:
In `@packages/interfold-contracts/test/fixtures/system.ts`:
- Line 413: Update the system fixture’s initialE3Program setup to deploy the
mock E3 program before Interfold initialization, or require a valid deployed
program instead of defaulting to ADDRESS_ONE. In
packages/interfold-contracts/test/Interfold.spec.ts lines 71-73, pass the
deployed mock address rather than AddressTwo; at lines 92-96, assert that this
deployed mock address is registered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b9a2c641-e885-42db-b59c-0af8fa1eddee

📥 Commits

Reviewing files that changed from the base of the PR and between ca2ff5c and df1c419.

📒 Files selected for processing (31)
  • agent/CRATES_ARCHITECTURE.md
  • agent/INVARIANTS.md
  • agent/flow-trace/00_INDEX.md
  • agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md
  • crates/keyshare/src/threshold_keyshare/effects/create_decryption_share.rs
  • crates/keyshare/src/threshold_keyshare/effects/initialize_dkg.rs
  • crates/keyshare/src/threshold_keyshare/handlers.rs
  • crates/keyshare/src/threshold_keyshare/state.rs
  • crates/keyshare/src/threshold_keyshare/state_tests.rs
  • crates/keyshare/src/threshold_keyshare/tests.rs
  • packages/interfold-contracts/README.md
  • packages/interfold-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/IInterfold.sol/IInterfold.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/interfold-contracts/artifacts/contracts/token/InterfoldTicketToken.sol/InterfoldTicketToken.json
  • packages/interfold-contracts/contracts/Interfold.sol
  • packages/interfold-contracts/contracts/interfaces/IInterfold.sol
  • packages/interfold-contracts/deploy/protocol/example.protocol.config.json
  • packages/interfold-contracts/ignition/modules/interfold.ts
  • packages/interfold-contracts/scripts/deployAndSave/interfold.ts
  • packages/interfold-contracts/scripts/deploymentRecords.ts
  • packages/interfold-contracts/scripts/protocol/actions.ts
  • packages/interfold-contracts/scripts/protocol/deployContracts.ts
  • packages/interfold-contracts/scripts/protocol/tx/interfold.ts
  • packages/interfold-contracts/scripts/protocol/types.ts
  • packages/interfold-contracts/scripts/protocol/validate.ts
  • packages/interfold-contracts/scripts/protocol/values.ts
  • packages/interfold-contracts/test/Interfold.spec.ts
  • packages/interfold-contracts/test/fixtures/system.ts
💤 Files with no reviewable changes (1)
  • packages/interfold-contracts/scripts/protocol/tx/interfold.ts

Comment thread crates/keyshare/src/threshold_keyshare/state.rs
Comment thread packages/interfold-contracts/ignition/modules/interfold.ts Outdated
ctrlc03
ctrlc03 previously approved these changes Aug 4, 2026
Persist terminal keyshare failures before timeout events. Bootstrap one production E3 program before Safe ownership, and restrict later registrations to the owner.

Refs #1765
@ctrlc03
ctrlc03 enabled auto-merge (squash) August 4, 2026 20:11
@ctrlc03
ctrlc03 merged commit d85aa4a into main Aug 4, 2026
37 checks passed
@ctrlc03
ctrlc03 deleted the fix/audit-remediations-28516 branch August 4, 2026 20:12
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.

Audit: remediate M-42, M-43, and M-39

2 participants