Skip to content

docs(token): document safe->C2C migration via CMA#532

Merged
0xisk merged 5 commits into
mainfrom
docs/c2c-migration-plan-cma
May 29, 2026
Merged

docs(token): document safe->C2C migration via CMA#532
0xisk merged 5 commits into
mainfrom
docs/c2c-migration-plan-cma

Conversation

@0xisk
Copy link
Copy Markdown
Member

@0xisk 0xisk commented May 29, 2026

<!-- Thank you for your interest in contributing to OpenZeppelin! -->

Types of changes

What types of changes does your code introduce to OpenZeppelin Midnight Contracts?
Put an `` in the boxes that apply

  • 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)

Fixes #118

PR Checklist

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

Summary by CodeRabbit

  • Documentation
    • Added migration plans outlining future support for contract-to-contract transfers and role management across access control and token contracts, detailing the staged rollout approach and preservation of ledger state during transitions.

Review Change Stack

0xisk added 5 commits May 29, 2026 11:14
Expand the NonFungibleToken migration-plan header to explain how the
safe/_unsafe deprecation is carried out on-chain through Midnight's
Contract Maintenance Authority (CMA).

Key rationale: the recipient type is the final
Either<Bytes<32>, ContractAddress> from day one because the CMA can
rotate a circuit's verifier key but cannot migrate ledger state. That
makes the future migration a pure VK rotation (VerifierKeyRemove +
VerifierKeyInsert for transfer, VerifierKeyRemove for _unsafeTransfer)
with the contract address and all ledger state preserved. Widening the
types later would require a ledger-layout rewrite the CMA cannot do.

Refs: #118
Replace the generic FN/_unsafeFN deprecation note with the concrete
guarded circuits and explain how the migration runs on-chain through
Midnight's Contract Maintenance Authority (CMA).

Rationale: the recipient type is the final Either<Bytes<32>,
ContractAddress> from day one because the CMA can rotate a circuit's
verifier key but cannot migrate ledger state, so the migration is a
pure VK rotation with address and state preserved.

Refs: #118
Add a structured migration-plan section to the MultiToken header (it
previously only noted "revise logic once C2C is available"), covering
the guarded circuits, their _unsafe variants, and how the migration is
carried out on-chain through Midnight's Contract Maintenance Authority
(CMA).

Rationale: the recipient type is the final Either<Bytes<32>,
ContractAddress> from day one because the CMA can rotate a circuit's
verifier key but cannot migrate ledger state, so the migration is a
pure VK rotation with address and state preserved.

Refs: #118
Add a structured migration-plan section to the Ownable header (it
previously only noted the unsafe circuits are "planned to become
deprecated"), covering transferOwnership / _transferOwnership, their
_unsafe variants, and how the migration is carried out on-chain through
Midnight's Contract Maintenance Authority (CMA).

Rationale: the owner type is the final Either<Bytes<32>,
ContractAddress> from day one because the CMA can rotate a circuit's
verifier key but cannot migrate ledger state, so the migration is a
pure VK rotation with address and state preserved.

Refs: #118
Add a structured migration-plan section to the AccessControl header (it
previously only noted the unsafe circuit is "planned to become
deprecated"), covering grantRole / _grantRole, _unsafeGrantRole, and how
the migration is carried out on-chain through Midnight's Contract
Maintenance Authority (CMA).

Rationale: the account type is the final Either<Bytes<32>,
ContractAddress> from day one because the CMA can rotate a circuit's
verifier key but cannot migrate ledger state, so the migration is a
pure VK rotation with address and state preserved.

Refs: #118
@0xisk 0xisk requested review from a team as code owners May 29, 2026 09:21
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Walkthrough

This PR updates contract documentation across five modules in the OpenZeppelin Compact Contracts library. Each module's header documentation is extended with detailed migration plans explaining how to evolve from "safe" single-recipient flows to contract-to-contract (C2C) capable flows, describing verifier-key rotation strategies and ledger-state preservation. No executable logic or public interface changes are made.

Changes

C2C Migration Planning Documentation

Layer / File(s) Summary
Migration plan documentation across all modules
contracts/src/access/AccessControl.compact, contracts/src/access/Ownable.compact, contracts/src/token/FungibleToken.compact, contracts/src/token/MultiToken.compact, contracts/src/token/NonFungibleToken.compact
Five module-level documentation sections are added or updated to describe the planned transition from "safe" single-recipient circuits to C2C-capable circuits. Each explains the use of Either<Bytes<32>, ContractAddress> types, deprecation and rollout phases across minor/major releases, verifier-key rotation by CMA, and how ledger state and contract addresses are preserved during transitions.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Suggested reviewers

  • pepebndc

Poem

🐰 Five docs now speak of futures bright,
C2C contracts shining in the light,
State preserved through rotation's dance,
Safe to unsafe, a guided advance.
Migration plans all mapped with care—
The ledger's heart stays rooted there! 💚

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'docs(token): document safe->C2C migration via CMA' accurately describes the primary change: adding documentation about migrating from safe recipient types to C2C-capable types through CMA verifier-key rotations across multiple contract modules.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 docs/c2c-migration-plan-cma

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

@0xisk 0xisk changed the title docs(token): document NFT safe->C2C migration via CMA docs(token): document safe->C2C migration via CMA May 29, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
contracts/src/token/NonFungibleToken.compact (1)

34-54: 💤 Low value

Consider clarifying which circuits the migration plan covers.

The migration plan mentions "transfer" and "_unsafeTransfer" specifically (lines 46, 48, 50), but the module has multiple guarded circuits (transfer, transferFrom, _transfer, _mint) and their corresponding _unsafe variants (_unsafeTransferFrom, _unsafeTransfer, _unsafeMint).

For consistency with FungibleToken.compact (lines 43-54), which uses placeholder notation like "FN" to represent the family of guarded circuits and explicitly lists all affected circuits, consider either:

  1. Listing all affected circuits explicitly: "ship transfer, transferFrom, _transfer, and _mint with the isContract guard removed and drop their _unsafe counterparts"
  2. Using clearer language to indicate the migration applies to all guarded transfer/mint circuits, not just the public transfer circuit

This improves clarity for implementers planning upgrades.

🤖 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 `@contracts/src/token/NonFungibleToken.compact` around lines 34 - 54, Update
the migration plan wording to clarify which circuits are covered by the C2C
migration: either explicitly list all guarded circuits and their unsafe
counterparts (e.g., transfer, transferFrom, _transfer, _mint and their _unsafe
variants _unsafeTransfer, _unsafeTransferFrom, _unsafeMint) where you currently
mention only `transfer` and `_unsafeTransfer`, or replace the singular names
with a clear family-level phrase such as "all guarded transfer/mint circuits
(transfer, transferFrom, _transfer, _mint) and their corresponding _unsafe*
variants" so readers know the plan applies to every guarded transfer/mint
circuit including their _unsafe versions.
🤖 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.

Nitpick comments:
In `@contracts/src/token/NonFungibleToken.compact`:
- Around line 34-54: Update the migration plan wording to clarify which circuits
are covered by the C2C migration: either explicitly list all guarded circuits
and their unsafe counterparts (e.g., transfer, transferFrom, _transfer, _mint
and their _unsafe variants _unsafeTransfer, _unsafeTransferFrom, _unsafeMint)
where you currently mention only `transfer` and `_unsafeTransfer`, or replace
the singular names with a clear family-level phrase such as "all guarded
transfer/mint circuits (transfer, transferFrom, _transfer, _mint) and their
corresponding _unsafe* variants" so readers know the plan applies to every
guarded transfer/mint circuit including their _unsafe versions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fcca365c-0f5f-4d82-9be5-4527e9293758

📥 Commits

Reviewing files that changed from the base of the PR and between 78a5c61 and 629b353.

📒 Files selected for processing (5)
  • contracts/src/access/AccessControl.compact
  • contracts/src/access/Ownable.compact
  • contracts/src/token/FungibleToken.compact
  • contracts/src/token/MultiToken.compact
  • contracts/src/token/NonFungibleToken.compact

Copy link
Copy Markdown
Contributor

@pepebndc pepebndc left a comment

Choose a reason for hiding this comment

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

Approved

@0xisk 0xisk merged commit 4a65da9 into main May 29, 2026
10 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.

Document Non-fungible Token Migration Plan

2 participants