Skip to content

Conversation

@james-toussaint
Copy link
Contributor

@james-toussaint james-toussaint commented Aug 12, 2025

Summary by Sourcery

Add ERC7984Rwa extension to support confidential Real World Assets with compliance enforcement, access control, pausing, freezing, and force transfer capabilities, along with interfaces, mock implementation, and extensive testing support

New Features:

  • Introduce ERC7984Rwa extension offering confidential Real World Assets support with compliance checks, role-based pausing, freezing, and force/regular transfer methods
  • Define IERC7984RwaBase and IERC7984Rwa interfaces along with compliance interface for RWA token standards
  • Provide ERC7984RwaMock contract to enable compliance toggling and encrypted handle management in tests

Enhancements:

  • Fix handle generation parameter in HandleAccessManager test

Tests:

  • Add comprehensive tests for ERC7984Rwa covering ERC165 support, pausable behavior, role management, confidential minting, burning, transfers, force transfers, and frozen balances
  • Introduce helpers for interface ID calculation and event result extraction

Summary by CodeRabbit

  • New Features
    • Added ERC7984Rwa extension for confidential Real World Assets: admin/agent roles, pause/unpause, block/unblock users, confidential freezing, mint/burn, force transfers, and batch operations.
  • Documentation
    • Added ERC7984Rwa entry to the token extension docs.
  • Tests
    • Added comprehensive ERC7984Rwa test suite and test helpers for interface IDs; removed one freezer-role test.
  • Refactor
    • Made freezing/restriction flows more configurable and removed freezer-role reliance in mocks.
  • Chores
    • Bumped openzeppelin-confidential-contracts to a minor version.

@netlify
Copy link

netlify bot commented Aug 12, 2025

Deploy Preview for confidential-tokens ready!

Name Link
🔨 Latest commit 09c2789
🔍 Latest deploy log https://app.netlify.com/projects/confidential-tokens/deploys/68d6af3b171fc7000860b3c3
😎 Deploy Preview https://deploy-preview-160--confidential-tokens.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@james-toussaint james-toussaint changed the title Add ERC7984Rwa extension. Add ERC7984Rwa extension Aug 12, 2025
@james-toussaint james-toussaint linked an issue Aug 26, 2025 that may be closed by this pull request
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 29, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds ERC7984Rwa: a confidential RWA extension (interface + abstract implementation) with admin/agent roles, pause/block controls, freezing, confidential mint/burn, and forced transfers. Refactors ERC7984 Restricted/Freezable internals, adds mocks, tests, interface helpers, and a docs changeset.

Changes

Cohort / File(s) Summary
Release metadata
\.changeset/new-crews-boil.md
Adds a changeset: minor bump for openzeppelin-confidential-contracts and documents new ERC7984Rwa extension.
RWA interface
contracts/interfaces/IERC7984Rwa.sol
New interface IERC7984Rwa (extends IERC7984, IERC165) exposing pause/block queries, frozen/available queries, confidential mint/burn, force transfers (with/without proofs), and multicall.
RWA extension
contracts/token/ERC7984/extensions/ERC7984Rwa.sol
New abstract ERC7984Rwa: adds AGENT_ROLE, onlyAdmin/onlyAgent modifiers, admin/agent management, pause/unpause, block/unblock, set confidential frozen, confidential mint/burn, forceConfidentialTransferFrom, and compliance pre/post hooks.
RWA mock
contracts/mocks/token/ERC7984RwaMock.sol
New mock implementing togglable compliantTransfer, createEncryptedAmount, test mint wrapper $_mint, emits PostTransfer/PostForceTransfer, and overrides pre/post transfer checks and handle validation.
Restricted internals
contracts/token/ERC7984/extensions/ERC7984Restricted.sol
Replaces direct per-address restriction calls with _checkRestrictionFrom and _checkRestrictionTo helpers; _checkRestriction remains core. No public API changes.
Freezable internals
contracts/token/ERC7984/extensions/ERC7984Freezable.sol
Removes _checkFreezer; adds _getUpdateAmountIfNotExceedingFrozenFrom and _refreshFrozenFrom; reworks _update to use these hooks and preserve TokensFrozen semantics.
Freezable mock & tests
contracts/mocks/token/ERC7984FreezableMock.sol, test/token/ERC7984/extensions/ERC7984Freezable.test.ts
Mock: removes FREEZER_ROLE/AccessControl gating, adds public $_setConfidentialFrozen wrapper and confidentialAvailableAccess. Tests: removes freezer-authorization test that asserted role gating.
RWA tests & helpers
test/token/ERC7984/extensions/ERC7984Rwa.test.ts, test/helpers/interface.ts
New comprehensive ERC7984Rwa test suite exercising ERC165, roles, pause/block, freeze, confidential mint/burn, force transfers, transfers (with/without proofs) and end-to-end FHE flows. Adds getFunctions and getInterfaceId test helpers.
Docs
contracts/token/README.adoc
Documents the ERC7984Rwa extension in extension lists and references.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin as Admin
  participant Agent as Agent
  participant RWA as ERC7984Rwa
  participant FHE as FHEVM

  rect rgb(245,248,255)
  note over Admin,RWA: Role setup
  Admin->>RWA: addAgent(agent)
  RWA-->>Admin: ok
  end

  rect rgb(245,255,245)
  note over Agent,RWA: Pause control
  Agent->>RWA: pause()
  RWA-->>Agent: ok
  Agent->>RWA: unpause()
  RWA-->>Agent: ok
  end

  rect rgb(255,248,240)
  note over Agent,RWA: Confidential mint (with proof)
  Agent->>FHE: build encryptedAmount + proof
  FHE-->>Agent: externalEuint64, proof
  Agent->>RWA: confidentialMint(to, extAmt, proof)
  RWA-->>Agent: euint64 minted
  end

  rect rgb(255,245,250)
  note over Agent,RWA: Forced transfer (no proof)
  Agent->>RWA: forceConfidentialTransferFrom(from,to,eAmt)
  alt compliant and not paused
    RWA-->>Agent: euint64 transferred
  else error
    RWA-->>Agent: revert
  end
  end
Loading
sequenceDiagram
  autonumber
  actor Agent as Agent
  participant RWA as ERC7984Rwa
  participant Restr as ERC7984Restricted
  participant Freez as ERC7984Freezable

  note over Agent,RWA: Transfer flow with restrictions and freezing
  Agent->>RWA: confidentialTransfer(from,to,eAmt)
  activate RWA
  RWA->>Restr: _checkRestrictionFrom(from)
  RWA->>Restr: _checkRestrictionTo(to)
  RWA->>Freez: _getUpdateAmountIfNotExceedingFrozenFrom(from,eAmt)
  Freez-->>RWA: eAmt' (possibly reduced)
  RWA->>RWA: _preTransferCheck(...)
  RWA->>RWA: super._update(from,to,eAmt')
  RWA->>Freez: _refreshFrozenFrom(from,transferred)
  RWA-->>Agent: euint64 transferred
  deactivate RWA
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

ignore-changeset

Poem

A hare in a vest with a ledger so bright,
I hide tiny carrots in ciphertext at night.
Agents hop in—pause, mint, or move—
Frozen piles thaw when the checks approve.
Rabbity secrets safe beneath the clover light. 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Add ERC7984Rwa extension" is a concise, single-sentence summary that directly reflects the PR's primary change — introducing the ERC7984Rwa extension along with its interfaces, mock, tests, and documentation to support confidential RWA functionality. It is specific and clear enough for a teammate scanning the history to understand the main change.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@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.

Actionable comments posted: 0

🧹 Nitpick comments (2)
contracts/mocks/token/ERC7984RwaMock.sol (2)

13-13: Remove unused private state to cut bytecode/gas

_frozenBalances is declared but never read/written. Drop it to reduce bytecode size.

-    mapping(address account => euint64 encryptedAmount) private _frozenBalances;

26-29: Optional: return explicitly for readability

Being explicit can aid reviewers and static analyzers; no behavior change.

     function createEncryptedAmount(uint64 amount) public returns (euint64 encryptedAmount) {
         FHE.allowThis(encryptedAmount = FHE.asEuint64(amount));
         FHE.allow(encryptedAmount, msg.sender);
+        return encryptedAmount;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0172d and f43ceaa.

📒 Files selected for processing (3)
  • contracts/mocks/token/ERC7984RwaMock.sol (1 hunks)
  • contracts/token/ERC7984/extensions/ERC7984Rwa.sol (1 hunks)
  • test/token/ERC7984/extensions/ERC7984Rwa.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/token/ERC7984/extensions/ERC7984Rwa.test.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-22T09:21:34.438Z
Learnt from: james-toussaint
PR: OpenZeppelin/openzeppelin-confidential-contracts#160
File: test/token/ERC7984/extensions/ERC7984Rwa.test.ts:474-479
Timestamp: 2025-09-22T09:21:34.438Z
Learning: For force transfers in ERC7984Freezable, the frozen balance should be reset to the new balance if the transfer amount exceeded the available balance. If the transfer amount was within the available balance, the frozen amount behavior needs clarification from the user.

Applied to files:

  • contracts/token/ERC7984/extensions/ERC7984Rwa.sol
📚 Learning: 2025-09-22T09:21:34.438Z
Learnt from: james-toussaint
PR: OpenZeppelin/openzeppelin-confidential-contracts#160
File: test/token/ERC7984/extensions/ERC7984Rwa.test.ts:474-479
Timestamp: 2025-09-22T09:21:34.438Z
Learning: In ERC7984Freezable force transfers, the frozen balance is reset to the new balance only when the transferred amount exceeds the available balance (balance - frozen). If the transferred amount is within the available balance, the frozen amount remains unchanged. This is implemented via FHE.select(FHE.gt(encryptedAmount, confidentialAvailable(account)), confidentialBalanceOf(account), frozen).

Applied to files:

  • contracts/token/ERC7984/extensions/ERC7984Rwa.sol
📚 Learning: 2025-09-16T10:32:50.913Z
Learnt from: arr00
PR: OpenZeppelin/openzeppelin-confidential-contracts#186
File: contracts/token/ERC7984/extensions/ERC7984Omnibus.sol:0-0
Timestamp: 2025-09-16T10:32:50.913Z
Learning: Custom errors are supported in require statements starting from Solidity 0.8.26 (via IR pipeline) and 0.8.27 (legacy pipeline). The syntax require(condition, CustomError(param)) is valid and compiles correctly in these versions.

Applied to files:

  • contracts/mocks/token/ERC7984RwaMock.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: boostsecurity - boostsecurityio/semgrep-pro
  • GitHub Check: coverage
  • GitHub Check: tests
🔇 Additional comments (4)
contracts/mocks/token/ERC7984RwaMock.sol (1)

31-37: Avoid $ in public function names (tooling/friction risk)

These helpers are public and the $ prefix can break tools and conventions. Prefer canonical names.

-    function $_setCompliantTransfer() public {
+    function setCompliantTransfer() public {
         compliantTransfer = true;
     }

-    function $_unsetCompliantTransfer() public {
+    function unsetCompliantTransfer() public {
         compliantTransfer = false;
     }

-    function $_mint(address to, uint64 amount) public returns (euint64 transferred) {
+    function mintForTest(address to, uint64 amount) public returns (euint64 transferred) {
         return _mint(to, FHE.asEuint64(amount));
     }

If tests rely on the old names, I can PR the updates to the spec files. Want me to push the rename across tests?

Also applies to: 39-41

contracts/token/ERC7984/extensions/ERC7984Rwa.sol (3)

246-251: Compile error: pure reads msg.sig

Reading msg.sig disallows pure. Make it view.

-    function _isForceTransfer() private pure returns (bool) {
+    function _isForceTransfer() private view returns (bool) {
         return
             msg.sig == FORCE_CONFIDENTIAL_TRANSFER_FROM_SIG ||
             msg.sig == FORCE_CONFIDENTIAL_TRANSFER_FROM_WITH_PROOF_SIG;
     }

115-118: Confirmed: compilers configured ≥ 0.8.27 — custom errors in require(...) are supported

Hardhat config sets solidity = 0.8.29 and foundry.toml sets solc_version = 0.8.27; ERC7984Rwa.sol pragma is ^0.8.27. No change required.


177-194: Force transfers bypass pause — enforce pause check here

_forceConfidentialTransferFrom calls super._update, skipping this contract’s whenNotPaused guard on _update. As written, agents can force-transfer while paused.

Add an explicit pause check at function start to retain pause semantics:

     function _forceConfidentialTransferFrom(
         address from,
         address to,
         euint64 encryptedAmount
     ) internal virtual returns (euint64 transferred) {
+        _requireNotPaused();
         if (!FHE.isInitialized(encryptedAmount)) {
             return encryptedAmount;
         }

Optionally document which checks are bypassed (from-side frozen/restriction, compliance) and which remain (pause, to-side restriction).

arr00 and others added 5 commits September 25, 2025 14:03
Copy link
Contributor Author

@james-toussaint james-toussaint left a comment

Choose a reason for hiding this comment

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

Can't approve but good to me 👍

@james-toussaint james-toussaint merged commit 72df2a3 into master Sep 29, 2025
15 checks passed
@james-toussaint james-toussaint deleted the feature/confidential-rwa branch September 29, 2025 07:59
@github-actions github-actions bot mentioned this pull request Oct 9, 2025
@github-actions github-actions bot mentioned this pull request Nov 12, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
@github-actions github-actions bot mentioned this pull request Dec 12, 2025
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.

Confidential RWA extension

3 participants