Skip to content

Move contractURI() to extension#310

Draft
arr00 wants to merge 5 commits intomasterfrom
chore/erc7984-metadata-extension
Draft

Move contractURI() to extension#310
arr00 wants to merge 5 commits intomasterfrom
chore/erc7984-metadata-extension

Conversation

@arr00
Copy link
Copy Markdown
Member

@arr00 arr00 commented Feb 24, 2026

The contractURI() function seems like it would belong best in an extension.

Summary by CodeRabbit

  • Breaking Changes

    • Core contract constructor signatures have been updated to remove the metadata URI parameter from initialization.
  • New Features

    • Added an optional metadata extension that provides contract-level URI support for implementations that require it.

@netlify
Copy link
Copy Markdown

netlify bot commented Feb 24, 2026

Deploy Preview for confidential-tokens ready!

Name Link
🔨 Latest commit 75906f1
🔍 Latest deploy log https://app.netlify.com/projects/confidential-tokens/deploys/69a0d7aa4c176c0008905c7b
😎 Deploy Preview https://deploy-preview-310--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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 24, 2026

Important

Review skipped

Draft detected.

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.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/erc7984-metadata-extension

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

Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (3)
contracts/token/ERC7984/extensions/ERC7984Metadata.sol (1)

13-17: Consider adding an internal _setContractURI setter for post-deployment URI updates.

The URI is currently write-once (constructor only). Subclasses that need to update it (e.g., after an IPFS migration) must override contractURI() entirely. Adding an internal setter following the same pattern as OpenZeppelin's ERC6909ContentURI._setContractURI provides composable extensibility without exposing an unguarded public surface.

✨ Suggested addition
 constructor(string memory contractURI_) {
     _contractURI = contractURI_;
 }

+/// `@dev` Sets the contract URI and emits a {ContractURIUpdated} event.
+function _setContractURI(string memory newContractURI) internal virtual {
+    _contractURI = newContractURI;
+    emit ContractURIUpdated();
+}
+
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/token/ERC7984/extensions/ERC7984Metadata.sol` around lines 13 - 17,
The contract stores the contract URI in the private variable _contractURI and
only sets it in the constructor, preventing subclasses from updating it; add an
internal setter named _setContractURI(string memory) that updates _contractURI
(mirroring OpenZeppelin's ERC6909ContentURI._setContractURI) so subclasses can
call _setContractURI(...) to change the value post-deployment while keeping the
setter internal and preserving the existing public contractURI() accessor.
contracts/interfaces/IERC7984Metadata.sol (1)

8-10: ContractURIUpdated() event missing from the ERC-7572 interface.

The canonical ERC-7572 interface is interface IERC7572 { function contractURI() external view returns (string memory); event ContractURIUpdated(); }, and the ContractURIUpdated() event is specified to help offchain indexers know when to refetch the metadata.

Its absence from IERC7984Metadata means the interface doesn't fully conform to ERC-7572, and consumers building on this interface won't have the standard event hook. Even if ERC7984Metadata today only sets the URI at construction, declaring the event here (and emitting it from a future _setContractURI setter) follows the ERC-7572 spec and aligns with how OpenZeppelin implements the same pattern in ERC6909ContentURI.

✨ Suggested addition
 interface IERC7984Metadata is IERC7984 {
+    /// `@dev` Emitted when the contract URI is updated. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572].
+    event ContractURIUpdated();
+
     /// `@dev` Returns the contract URI. Should be formatted as described in https://eips.ethereum.org/EIPS/eip-7572[ERC-7572].
     function contractURI() external view returns (string memory);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/interfaces/IERC7984Metadata.sol` around lines 8 - 10, Add the
missing ERC-7572 event to the interface: declare the ContractURIUpdated (or
ContractURIUpdated()) event inside IERC7984Metadata alongside the existing
contractURI() function so the interface fully conforms to ERC-7572; update
implementing contracts (e.g., ERC7984Metadata) to emit ContractURIUpdated when a
future _setContractURI or similar setter changes the URI.
test/token/ERC7984/ERC7984.test.ts (1)

48-58: Consider adding a negative ERC7984Metadata interface check.

The ERC165 block already asserts ERC7984ERC20Wrapper and ERC7984RWA return false. Since the explicit goal of this PR is to gate contractURI() behind an opt-in extension, a matching negative assertion for INTERFACE_IDS.ERC7984Metadata would close the loop and prevent regressions.

🛡️ Suggested addition
 await expect(this.token.supportsInterface(INTERFACE_IDS.ERC7984)).to.eventually.be.true;
 await expect(this.token.supportsInterface(INTERFACE_IDS.ERC7984ERC20Wrapper)).to.eventually.be.false;
 await expect(this.token.supportsInterface(INTERFACE_IDS.ERC7984RWA)).to.eventually.be.false;
+await expect(this.token.supportsInterface(INTERFACE_IDS.ERC7984Metadata)).to.eventually.be.false;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/token/ERC7984/ERC7984.test.ts` around lines 48 - 58, Add a negative
ERC7984Metadata interface check in the ERC165 tests: in the describe('ERC165')
block add an assertion using
this.token.supportsInterface(INTERFACE_IDS.ERC7984Metadata) and expect it
to.eventually.be.false (matching the style of the existing supportsInterface
checks), so the test explicitly verifies that INTERFACE_IDS.ERC7984Metadata is
not supported by default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@contracts/interfaces/IERC7984Metadata.sol`:
- Line 3: The pragma in IERC7984Metadata.sol is set to ^0.8.24 which is
inconsistent with the rest of the PR; update the Solidity pragma in that
interface (IERC7984Metadata) to ^0.8.27 so it matches the other contracts and
avoid compiler-version mismatches, then recompile/tests to verify compatibility
with the implementing contracts.

---

Nitpick comments:
In `@contracts/interfaces/IERC7984Metadata.sol`:
- Around line 8-10: Add the missing ERC-7572 event to the interface: declare the
ContractURIUpdated (or ContractURIUpdated()) event inside IERC7984Metadata
alongside the existing contractURI() function so the interface fully conforms to
ERC-7572; update implementing contracts (e.g., ERC7984Metadata) to emit
ContractURIUpdated when a future _setContractURI or similar setter changes the
URI.

In `@contracts/token/ERC7984/extensions/ERC7984Metadata.sol`:
- Around line 13-17: The contract stores the contract URI in the private
variable _contractURI and only sets it in the constructor, preventing subclasses
from updating it; add an internal setter named _setContractURI(string memory)
that updates _contractURI (mirroring OpenZeppelin's
ERC6909ContentURI._setContractURI) so subclasses can call _setContractURI(...)
to change the value post-deployment while keeping the setter internal and
preserving the existing public contractURI() accessor.

In `@test/token/ERC7984/ERC7984.test.ts`:
- Around line 48-58: Add a negative ERC7984Metadata interface check in the
ERC165 tests: in the describe('ERC165') block add an assertion using
this.token.supportsInterface(INTERFACE_IDS.ERC7984Metadata) and expect it
to.eventually.be.false (matching the style of the existing supportsInterface
checks), so the test explicitly verifies that INTERFACE_IDS.ERC7984Metadata is
not supported by default.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 136840e and 89c4dde.

📒 Files selected for processing (28)
  • contracts/interfaces/IERC7984.sol
  • contracts/interfaces/IERC7984Metadata.sol
  • contracts/mocks/docs/ERC7984MintableBurnable.sol
  • contracts/mocks/token/ERC7984ERC20WrapperMock.sol
  • contracts/mocks/token/ERC7984FreezableMock.sol
  • contracts/mocks/token/ERC7984MetadataMock.sol
  • contracts/mocks/token/ERC7984Mock.sol
  • contracts/mocks/token/ERC7984ObserverAccessMock.sol
  • contracts/mocks/token/ERC7984ReentrantMock.sol
  • contracts/mocks/token/ERC7984RwaMock.sol
  • contracts/mocks/token/ERC7984VotesMock.sol
  • contracts/token/ERC7984/ERC7984.sol
  • contracts/token/ERC7984/extensions/ERC7984Metadata.sol
  • test/finance/ERC7821WithExecutor.test.ts
  • test/finance/VestingWalletCliffConfidential.test.ts
  • test/finance/VestingWalletConfidential.behavior.ts
  • test/finance/VestingWalletConfidential.test.ts
  • test/finance/VestingWalletConfidentialFactory.test.ts
  • test/helpers/interface.ts
  • test/token/ERC7984/ERC7984.test.ts
  • test/token/ERC7984/ERC7984Votes.test.ts
  • test/token/ERC7984/extensions/ERC7984ERC20Wrapper.test.ts
  • test/token/ERC7984/extensions/ERC7984Freezable.test.ts
  • test/token/ERC7984/extensions/ERC7984Metadata.test.ts
  • test/token/ERC7984/extensions/ERC7984ObserverAccess.test.ts
  • test/token/ERC7984/extensions/ERC7984Omnibus.test.ts
  • test/token/ERC7984/extensions/ERC7984Restricted.test.ts
  • test/token/ERC7984/extensions/ERC7984Rwa.test.ts
💤 Files with no reviewable changes (2)
  • test/token/ERC7984/extensions/ERC7984Freezable.test.ts
  • contracts/interfaces/IERC7984.sol

@arr00 arr00 changed the title Move contractIURI() to extension Move contractURI() to extension Feb 24, 2026
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