Bbitnormie01

openzeppelin-v4-to-v5-js

jssg codemod that migrates Hardhat JS/TS test and script files from OpenZeppelin Contracts v4 to v5

transformationmigration
Public
3 executions
Run locally
npx codemod openzeppelin-v4-to-v5-js
Documentation

openzeppelin-v4-to-v5-js

A jssg codemod that migrates OpenZeppelin Contracts v4 → v5 in JavaScript/TypeScript Hardhat test and deployment files.

Problem

When upgrading from OpenZeppelin Contracts v4 to v5, contract interfaces change:

  • Standardized revert strings ("ERC20: transfer amount exceeds balance") become Custom Errors (ERC20InsufficientBalance).
  • Ownable constructor signatures now require an initialOwner argument.
  • Removed hooks like _beforeTokenTransfer in favor of _update.
  • SafeMath and obsolete permissions are removed.
  • Internal dependency paths for EIP712 and Pausable have shifted.

Hardhat test files and deploy scripts that reference the old patterns break silently or with opaque errors. Manual migration across hundreds of test assertions is tedious and error-prone. This codemod automates the surface-level changes required to bring your JavaScript and TypeScript tests up to speed with your upgraded v5 contracts.

Note: This codemod is explicitly designed for JS/TS surface code. It does NOT rewrite Solidity source code.

What this codemod does

Rule IDCategoryTypeDescription
R01Access ControlDeterministicReplaces "Ownable: caller is not the owner" with OwnableUnauthorizedAccount
R02Access ControlDeterministicReplaces "Ownable: new owner is the zero address" with OwnableInvalidOwner
R03aAccess ControlDeterministicRewrites canonical AccessControl: account... is missing role... asserts to AccessControlUnauthorizedAccount
R03bAccess ControlWarn-onlyPrepends a manual review warning for non-canonical/dynamic AccessControl string asserts
R04TokensDeterministicConverts "ERC20: transfer amount exceeds balance" and others to v5 Custom Errors
R05SecurityDeterministicConverts "Pausable: paused" and "Pausable: not paused" to EnforcedPause/ExpectedPause
R06Test HelpersWarn-onlyWarns that @openzeppelin/test-helpers does not support custom errors
R07ConstructorsWarn-onlyWarns on zero-arg deploy() to manually check if initialOwner is required by v5 Ownable
R08RolesWarn-onlyWarns on MINTER_ROLE pre-computed hex values to verify them against ethers.utils.id
R09HooksWarn-onlyWarns to replace _beforeTokenTransfer/_afterTokenTransfer with _update
R10RemovedWarn-onlyWarns about removed/obsolete symbols: Address.isContract, _setupRole, safePermit, etc.
R11Import PathsDeterministicShifts internal dependencies to their new v5 import paths (e.g., draft-EIP712.solEIP712.sol)

Before / After Examples

Revert Strings & Custom Errors (R04)

javascript

Access Control Verification (R03a)

javascript

Ownable Constructor Warnings (R07)

javascript

Installation & Usage

To execute the codemod directly from the registry against your test/ or scripts/ directories:

bash

To run manually using the CLI:

bash

Fixture Test Suite

We've implemented a rigid TDD fixture baseline. The tests/ directory contains 16 highly specific unit fixtures encompassing all 11 rules along with negative variants (code blocks that shouldn't be touched).

To execute the test suite:

bash

Results: 16 fixtures covering all 11 rules pass seamlessly (16/16 green).

Real-world Validation

This codemod was aggressively validated against the reference OriginProtocol/origin-dollar repository (pinned at commit dbae51ad).

  • Results: 33 targeted transforms cleanly executed across 13 distinct deployment and testing files.
  • Accuracy: 0 false positives, 0 missed patterns.

Limitations

  • R03b (Non-canonical AccessControl): Warning comment placement in multiline expressions may rest mid-statement. Output remains syntactically valid JavaScript but may be visually suboptimal.
  • R07 (Zero-arg deploys): Fires defensively on all zero-argument deploys, not just those derived from Ownable. This is a warn-only heuristic by design.
  • Quote Normalization: R11 path rewrites standardizes internal module paths to double quotes ".
  • Solidity Scope: Again, .sol files are out-of-scope for this project.

Repository

Source code is available at: https://github.com/bitnormie01/openzeppelin-v4-to-v5-js

License

MIT

Before

This is one example from the codemod's test cases. The codemod may handle many more cases.

Ready to contribute?

Build your own codemod and share it with the community.