Skip to content

feat(multisig): merge post-release suite to main - #593

Closed
0xisk wants to merge 6 commits into
mainfrom
chore/merge-post-release-to-main
Closed

feat(multisig): merge post-release suite to main#593
0xisk wants to merge 6 commits into
mainfrom
chore/merge-post-release-to-main

Conversation

@0xisk

@0xisk 0xisk commented Jun 15, 2026

Copy link
Copy Markdown
Member

Types of changes

What types of changes does your code introduce to OpenZeppelin Midnight Contracts?

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Closes #471
Closes #476
Closes #477
Closes #478
Closes #479
Closes #480
Closes #481
Closes #474

Merges the self-contained multisig contract suite from post-release into main. The suite was developed and reviewed on post-release across #378, #424, and #526; this PR brings it forward onto the current main.

What lands

Module / preset Closes
Signer / SignerManager — configurable M-of-N signer registry #471
ProposalManager #476
ShieldedTreasury (stateful) #477
ShieldedTreasuryStateless #478
UnshieldedTreasury #479
ShieldedMultiSig preset (ledger-backed) #480
ShieldedMultiSigV2 preset (stateless vault) #481
Forwarder / ForwarderPrivate + per-recipient presets #474

Plus supporting Utils additions (selfAsRecipient, isContractAddress, UINT128_MAX) and their tests.

Explicitly out of scope (left open)

Merge mechanics

The multisig modules import only other multisig modules plus the Compact standard library, so they are unaffected by main's per-module Initializable split (#562), the pksk refactor, and the witness relocation. Conflicts were limited to shared infra files and resolved in favour of main's conventions while preserving the multisig additions:

  • .gitignore, CHANGELOG.md: keep both sides' entries.
  • contracts/package.json: keep main's hierarchical build + SKIP_ZK test scripts and modern dependency versions; re-add fast-check.
  • contracts/vitest.config.ts: keep main's per-.ts 95% coverage gate.
  • contracts/src/utils/test/utils.test.ts: keep both describe blocks.
  • yarn.lock: regenerated via yarn install.

All 21 multisig .compact modules compile cleanly.

Supersedes #577, which is now stale/conflicting against the current main.

PR Checklist

Further comments

This is a forward-merge of already-reviewed work, so the diff is dominated by the new multisig/ tree (new files, no conflicts) and the witnesses currently sit under src/multisig/witnesses/ rather than main's newer test/witnesses/ layout (#528). Aligning that layout can be a follow-up alongside #565.

Summary by CodeRabbit

  • New Features

    • Added a comprehensive multisig contract suite enabling configurable M-of-N signer governance.
    • Introduced shielded and unshielded treasury modules for managing token deposits and transfers.
    • Added proposal management system with approval tracking and lifecycle controls.
    • Introduced forwarder modules for flexible fund routing with multiple deployment presets.
    • Note: Signature verification is currently stubbed pending underlying cryptographic primitives.
  • Chores

    • Updated build system and dependencies to support multisig contract compilation.

andrew-fleming and others added 6 commits May 5, 2026 14:25
Co-authored-by: 0xisk <iskander.andrews@openzeppelin.com>
Co-authored-by: 0xisk <0xisk@proton.me>
Signed-off-by: 0xisk <0xisk@proton.me>
Co-authored-by: andrew <fleming-andrew@protonmail.com>
Co-authored-by: 0xisk <iskander.andrews@openzeppelin.com>
Bring the self-contained multisig contract suite from `post-release`
into `main`: the M-of-N `Signer` / `SignerManager` registry,
`ProposalManager`, stateful `ShieldedTreasury` and
`ShieldedTreasuryStateless`, `UnshieldedTreasury`, the `Forwarder` /
`ForwarderPrivate` modules with per-recipient presets, and the
`ShieldedMultiSig` / `ShieldedMultiSigV2` presets.

The suite imports only other multisig modules plus the standard
library, so it is unaffected by main's per-module Initializable split
(#562), the pk->sk refactor, and the witness relocation. Conflicts
were limited to shared infra files and resolved in favour of main's
conventions while preserving the multisig additions:

* .gitignore, CHANGELOG.md: keep both sides' entries.
* contracts/package.json: keep main's hierarchical build, SKIP_ZK
  test scripts, and modern dep versions; re-add fast-check.
* contracts/vitest.config.ts: keep main's per-`.ts` 95% coverage gate.
* contracts/src/utils/test/utils.test.ts: keep both describe blocks.
* yarn.lock: regenerated via yarn install.

All 21 multisig `.compact` modules compile cleanly. Supersedes #577.
@0xisk
0xisk requested review from a team as code owners June 15, 2026 10:26
@0xisk 0xisk mentioned this pull request Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

This PR adds a multisig contract suite under contracts/src/multisig, including signer registries, proposal and treasury modules, forwarder presets, two shielded multisig presets, simulator and witness scaffolding, tests, utility helpers, and build/changelog updates.

Changes

Multisig contract suite

Layer / File(s) Summary
Tooling and utility support
.gitignore, CHANGELOG.md, contracts/package.json, turbo.json, contracts/src/utils/...
Adds multisig build wiring, fast-check, changelog and ignore updates, plus selfAsRecipient() and UINT128_MAX() with mock, simulator, and tests.
Signer registries and simulator support
contracts/src/multisig/Signer.compact, contracts/src/multisig/SignerManager.compact, contracts/src/multisig/test/{mocks,simulators}/*Signer*, contracts/src/multisig/witnesses/*Signer*, contracts/src/multisig/test/Signer*.test.ts
Adds generic signer registry modules with initialization, membership, threshold, and mutation circuits, together with mocks, simulators, witness stubs, and tests.
Proposal and treasury modules
contracts/src/multisig/{ProposalManager,ShieldedTreasury,UnshieldedTreasury}.compact, contracts/src/multisig/test/{mocks,simulators}/*{Proposal,Treasury}*, contracts/src/multisig/witnesses/*{Proposal,Treasury}*, contracts/src/multisig/test/{ProposalManager,ShieldedTreasury}.test.ts
Adds proposal lifecycle storage plus shielded and unshielded treasury accounting modules, with supporting wrappers, simulators, witnesses, and tests.
Forwarders and recipient presets
contracts/src/multisig/{Forwarder,ForwarderPrivate}.compact, contracts/src/multisig/presets/forwarder/*, contracts/src/multisig/test/{mocks,presets,simulators}/...Forwarder*, contracts/src/multisig/witnesses/...Forwarder*, contracts/src/multisig/test/{Forwarder,ForwarderPrivate}.test.ts
Adds public and commitment-based forwarders, shielded and unshielded preset wrappers, and supporting test, simulator, and witness infrastructure.
Ledger-backed shielded multisig preset
contracts/src/multisig/presets/ShieldedMultiSig.compact, contracts/src/multisig/test/simulators/ShieldedMultiSigSimulator.ts, contracts/src/multisig/witnesses/ShieldedMultiSigWitnesses.ts, contracts/src/multisig/test/ShieldedMultiSig.test.ts
Adds a preset that composes signer management, proposal tracking, approval bookkeeping, and shielded treasury execution with end-to-end simulator coverage.
Stateless shielded multisig preset
contracts/src/multisig/ShieldedTreasuryStateless.compact, contracts/src/multisig/presets/ShieldedMultiSigV2.compact, contracts/src/multisig/test/mocks/MockShieldedTreasuryStateless.compact, contracts/src/multisig/test/simulators/ShieldedMultiSigV2Simulator.ts, contracts/src/multisig/witnesses/ShieldedMultiSigV2Witnesses.ts, contracts/src/multisig/test/ShieldedMultiSigV2.test.ts
Adds a stateless shielded treasury and a second multisig preset using signer commitments, nonce-bound execution, and stubbed signature verification.

Sequence Diagram(s)

sequenceDiagram
  participant Signer
  participant ShieldedMultiSig
  participant ProposalManager
  participant ShieldedTreasury

  Signer->>ShieldedMultiSig: createShieldedProposal(...)
  ShieldedMultiSig->>ProposalManager: _createProposal(...)

  Signer->>ShieldedMultiSig: approveProposal(id)
  ShieldedMultiSig->>ProposalManager: assertProposalActive(id)

  Signer->>ShieldedMultiSig: executeShieldedProposal(id)
  ShieldedMultiSig->>ShieldedTreasury: _send(recipient, color, amount)
  ShieldedMultiSig->>ProposalManager: _markExecuted(id)
Loading
sequenceDiagram
  participant Relayer
  participant ShieldedMultiSigV2
  participant SignerSet
  participant ShieldedTreasuryStateless

  Relayer->>ShieldedMultiSigV2: execute(to, amount, coin, pubkeys, signatures)
  ShieldedMultiSigV2->>ShieldedMultiSigV2: compute nonce-bound message hash
  ShieldedMultiSigV2->>SignerSet: verify commitments and threshold
  ShieldedMultiSigV2->>ShieldedTreasuryStateless: _send(coin, recipient, amount)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • OpenZeppelin/compact-contracts#470 — This PR adds the multisig suite modules, presets, tests, and build wiring described by the umbrella issue.
  • OpenZeppelin/compact-contracts#565 — This PR introduces the forwarder modules and presets that the issue discusses with code-specific review feedback.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • andrew-fleming

Poem

🐇 I found a vault beneath the clover,
with signers, treasuries, and a forwarder rover.
Proposals hopped in neat array,
while shielded coins whisked on their way.
A nonce now twitches its whiskered nose—
and multisig blooms where midnight grows.

✨ 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 chore/merge-post-release-to-main

@0xisk

0xisk commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

Superseded by #594, which opens the merge directly from post-release so Andrew's original commit history is preserved instead of sitting under a synthetic merge branch. Same issue links carry over to #594.

@0xisk 0xisk closed this Jun 15, 2026
@0xisk
0xisk deleted the chore/merge-post-release-to-main branch June 15, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants