Skip to content

Solidity: Make ERC20 permit optional when votes is enabled#778

Merged
ericglau merged 7 commits intoOpenZeppelin:masterfrom
ericglau:votespermit
Feb 26, 2026
Merged

Solidity: Make ERC20 permit optional when votes is enabled#778
ericglau merged 7 commits intoOpenZeppelin:masterfrom
ericglau:votespermit

Conversation

@ericglau
Copy link
Member

@ericglau ericglau commented Feb 24, 2026

In OpenZeppelin Contracts v5, the Votes module has its own EIP712 and Nonces built-in, so it no longer implicitly requires ERC20Permit. Permit remains useful for gasless token transfers, but is no longer tied to Votes functionality.

However if ERC20Permit is not used, the user's contract needs to initialize the EIP712 domain separator.

@ericglau ericglau requested review from a team as code owners February 24, 2026 20:21
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

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.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This pull request decouples ERC20Permit from ERC20Votes in the OpenZeppelin Wizard. Previously, enabling ERC20Votes automatically included ERC20Permit; now Permit is optional and independent. Changes include core logic modifications, UI updates to reflect the decoupling, and documentation updates describing the new behavior.

Changes

Cohort / File(s) Summary
Release Notes
.changeset/lucky-pianos-poke.md, .changeset/wide-pianos-pay.md
Added changesets documenting patch releases for @openzeppelin/wizard and @openzeppelin/wizard-common, noting the behavioral change making ERC20Permit optional with ERC20Votes.
Core Logic
packages/core/solidity/src/erc20.ts
Removed implicit ERC20Permit requirement when votes are enabled; addVotes no longer enforces ERC20Permit presence, allowing independent feature selection.
Documentation & Descriptions
packages/common/src/ai/descriptions/solidity.ts
Updated ERC20Permit description to mention vote delegation as an additional outcome when Votes feature is enabled.
UI Components
packages/ui/src/solidity/ERC20Controls.svelte
Decoupled Permit checkbox state from Votes option; updated help text for both Permit and Votes sections to provide guidance on optional gasless delegation via Permit.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • CoveMB
  • brozorec
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: making ERC20 permit optional when votes is enabled, which matches the core functionality change across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description clearly explains the context (OpenZeppelin Contracts v5 changes), the reason for the change (Votes module now has built-in EIP712 and Nonces), and the implications (ERC20Permit is now optional). The description directly relates to the changeset which decouples ERC20Permit from ERC20Votes across core logic and UI.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Caution

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

⚠️ Outside diff range comments (1)
packages/core/solidity/src/erc20.ts (1)

118-125: ⚠️ Potential issue | 🟠 Major

Add test coverage for the { permit: false, votes: true } combination.

This newly enabled path is not currently covered by tests. Existing tests include permit: true alone, votes: true alone, and both together, but not permit: false, votes: true. Add a snapshot/unit test case verifying:

  1. ERC20Permit is absent from the generated output
  2. The standalone Nonces override (set up in addVotes at lines 194–203) is present and correct
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/solidity/src/erc20.ts` around lines 118 - 125, Add a
unit/snapshot test that exercises the combination { permit: false, votes: true }
by invoking the same generator used by the existing tests (the ones that cover
permit:true, votes:true, and both together) but passing allOpts with permit:
false and votes: true; assert that the generated output does NOT include the
ERC20Permit contract (verify absence of "ERC20Permit") and that the Nonces
override added by addVotes (the standalone Nonces override created in addVotes)
is present and matches the expected override shape and contents used in the
other votes tests. Use the same test harness and snapshot style as the existing
ERC20 tests so the new case sits alongside the current coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/core/solidity/src/erc20.ts`:
- Around line 118-125: Add a unit/snapshot test that exercises the combination {
permit: false, votes: true } by invoking the same generator used by the existing
tests (the ones that cover permit:true, votes:true, and both together) but
passing allOpts with permit: false and votes: true; assert that the generated
output does NOT include the ERC20Permit contract (verify absence of
"ERC20Permit") and that the Nonces override added by addVotes (the standalone
Nonces override created in addVotes) is present and matches the expected
override shape and contents used in the other votes tests. Use the same test
harness and snapshot style as the existing ERC20 tests so the new case sits
alongside the current coverage.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f067b9f and 9810e80.

📒 Files selected for processing (5)
  • .changeset/lucky-pianos-poke.md
  • .changeset/wide-pianos-pay.md
  • packages/common/src/ai/descriptions/solidity.ts
  • packages/core/solidity/src/erc20.ts
  • packages/ui/src/solidity/ERC20Controls.svelte

@ernestognw
Copy link
Member

the Votes module now has its own EIP712 and Nonces built-in, so delegateBySig works without Permit

A Permit and delegateBySig are different things. A delegate can't transfer the user's tokens. Permit is designed to avoid the approve + transferFrom workflow, which is still an issue if a Votes token.

Permit is now optional and only needed if you want the public DOMAIN_SEPARATOR()

Note that we no longer recommend DOMAIN_SEPARATOR in favor of ERC-5267, which Votes supports already. See OpenZeppelin/openzeppelin-contracts#6363

@ericglau ericglau requested a review from ernestognw February 24, 2026 20:40
Copy link
Member

@ernestognw ernestognw left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks @ericglau

Copy link
Member

@ernestognw ernestognw left a comment

Choose a reason for hiding this comment

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

LGTM

@ericglau ericglau enabled auto-merge (squash) February 26, 2026 01:52
@ericglau ericglau merged commit f2e8252 into OpenZeppelin:master Feb 26, 2026
21 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Feb 26, 2026
@ericglau ericglau deleted the votespermit branch February 26, 2026 13:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants