From 7d557a56e4a2a040bc5991c5a3d8496f73edae83 Mon Sep 17 00:00:00 2001 From: Elisa Falk Date: Mon, 12 May 2025 18:30:08 +0000 Subject: [PATCH 1/4] Refactor upgradeable functionality in governor.ts and set-upgradeable.ts --- packages/core/solidity/src/governor.ts | 4 +-- packages/core/solidity/src/set-upgradeable.ts | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/core/solidity/src/governor.ts b/packages/core/solidity/src/governor.ts index a8d64f010..320050276 100644 --- a/packages/core/solidity/src/governor.ts +++ b/packages/core/solidity/src/governor.ts @@ -7,7 +7,7 @@ import { OptionsError } from './error'; import { setAccessControl } from './set-access-control'; import { printContract } from './print'; import { setInfo } from './set-info'; -import { setUpgradeable } from './set-upgradeable'; +import { setUpgradeableGovernor } from './set-upgradeable'; import { defineFunctions } from './utils/define-functions'; import { durationToBlocks, durationToTimestamp } from './utils/duration'; import { clockModeDefault, type ClockMode } from './set-clock-mode'; @@ -99,7 +99,7 @@ export function buildGovernor(opts: GovernorOptions): Contract { addTimelock(c, allOpts); setAccessControl(c, allOpts.access); - setUpgradeable(c, allOpts.upgradeable, allOpts.access); + setUpgradeableGovernor(c, allOpts.upgradeable); setInfo(c, allOpts.info); return c; diff --git a/packages/core/solidity/src/set-upgradeable.ts b/packages/core/solidity/src/set-upgradeable.ts index ff6502805..92f769468 100644 --- a/packages/core/solidity/src/set-upgradeable.ts +++ b/packages/core/solidity/src/set-upgradeable.ts @@ -42,6 +42,41 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc } } +export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) { + if (upgradeable === false) { + return; + } + + c.upgradeable = true; + + c.addParent({ + name: 'Initializable', + path: '@openzeppelin/contracts/proxy/utils/Initializable.sol', + }); + + switch (upgradeable) { + case 'transparent': + break; + + case 'uups': { + const UUPSUpgradeable = { + name: 'UUPSUpgradeable', + path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', + }; + c.addParent(UUPSUpgradeable); + c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); + c.addModifier('onlyGovernance', functions._authorizeUpgrade); + c.setFunctionBody([], functions._authorizeUpgrade); + break; + } + + default: { + const _: never = upgradeable; + throw new Error('Unknown value for `upgradeable`'); + } + } +} + const functions = defineFunctions({ _authorizeUpgrade: { args: [{ name: 'newImplementation', type: 'address' }], From 4b2b27c889f815e1a57dfb1ff05cb70d98f6f23f Mon Sep 17 00:00:00 2001 From: Elisa Falk Date: Tue, 13 May 2025 20:05:36 +0000 Subject: [PATCH 2/4] Refactor upgradeable handling in set-upgradeable.ts by extracting common logic into helper functions for improved code clarity and maintainability. --- .changeset/refactor-upgradeable-functions.md | 5 ++ packages/core/solidity/src/set-upgradeable.ts | 63 ++++++++++--------- 2 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 .changeset/refactor-upgradeable-functions.md diff --git a/.changeset/refactor-upgradeable-functions.md b/.changeset/refactor-upgradeable-functions.md new file mode 100644 index 000000000..e5c49fe3c --- /dev/null +++ b/.changeset/refactor-upgradeable-functions.md @@ -0,0 +1,5 @@ +--- +"@openzeppelin/wizard-solidity": patch +--- + +Refactor upgradeable handling in Governor contracts by extracting common logic between `setUpgradeable` and `setUpgradeableGovernor` into helper functions. ([#544](https://github.com/OpenZeppelin/contracts-wizard/pull/544)) \ No newline at end of file diff --git a/packages/core/solidity/src/set-upgradeable.ts b/packages/core/solidity/src/set-upgradeable.ts index 92f769468..682429393 100644 --- a/packages/core/solidity/src/set-upgradeable.ts +++ b/packages/core/solidity/src/set-upgradeable.ts @@ -7,9 +7,10 @@ export const upgradeableOptions = [false, 'transparent', 'uups'] as const; export type Upgradeable = (typeof upgradeableOptions)[number]; -export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) { + +function setupUpgradeableCommon(c: ContractBuilder, upgradeable: Upgradeable) { if (upgradeable === false) { - return; + return false; } c.upgradeable = true; @@ -19,59 +20,65 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc path: '@openzeppelin/contracts/proxy/utils/Initializable.sol', }); + return true; +} + + +function setupUUPS(c: ContractBuilder, applyAccessControl: () => void) { + const UUPSUpgradeable = { + name: 'UUPSUpgradeable', + path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', + }; + c.addParent(UUPSUpgradeable); + c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); + + + applyAccessControl(); + + c.setFunctionBody([], functions._authorizeUpgrade); +} + +export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) { + if (!setupUpgradeableCommon(c, upgradeable)) { + return; + } + switch (upgradeable) { case 'transparent': break; case 'uups': { - requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader'); - const UUPSUpgradeable = { - name: 'UUPSUpgradeable', - path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', - }; - c.addParent(UUPSUpgradeable); - c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); - c.setFunctionBody([], functions._authorizeUpgrade); + setupUUPS(c, () => { + requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader'); + }); break; } default: { - const _: never = upgradeable; + const _: never = upgradeable as Exclude; throw new Error('Unknown value for `upgradeable`'); } } } export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) { - if (upgradeable === false) { + if (!setupUpgradeableCommon(c, upgradeable)) { return; } - c.upgradeable = true; - - c.addParent({ - name: 'Initializable', - path: '@openzeppelin/contracts/proxy/utils/Initializable.sol', - }); - switch (upgradeable) { case 'transparent': break; case 'uups': { - const UUPSUpgradeable = { - name: 'UUPSUpgradeable', - path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', - }; - c.addParent(UUPSUpgradeable); - c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); - c.addModifier('onlyGovernance', functions._authorizeUpgrade); - c.setFunctionBody([], functions._authorizeUpgrade); + setupUUPS(c, () => { + c.addModifier('onlyGovernance', functions._authorizeUpgrade); + }); break; } default: { - const _: never = upgradeable; + const _: never = upgradeable as Exclude; throw new Error('Unknown value for `upgradeable`'); } } From 1ea2d35adb017a8ebc0f627b56f4b228720744c2 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 13 May 2025 17:38:11 -0400 Subject: [PATCH 3/4] Update changeset --- .changeset/refactor-upgradeable-functions.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.changeset/refactor-upgradeable-functions.md b/.changeset/refactor-upgradeable-functions.md index e5c49fe3c..97fb0a377 100644 --- a/.changeset/refactor-upgradeable-functions.md +++ b/.changeset/refactor-upgradeable-functions.md @@ -1,5 +1,7 @@ --- -"@openzeppelin/wizard-solidity": patch +'@openzeppelin/wizard': patch --- -Refactor upgradeable handling in Governor contracts by extracting common logic between `setUpgradeable` and `setUpgradeableGovernor` into helper functions. ([#544](https://github.com/OpenZeppelin/contracts-wizard/pull/544)) \ No newline at end of file +Use `onlyGovernance` to restrict upgrades for Governor with UUPS +- **Potentially breaking changes**: + - Governor with UUPS: `_authorizeUpgrade` function is restricted by `onlyGovernance` instead of `onlyOwner` From 315ee8ca97a30845b006768543a9fd5a7b8ba0b0 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Tue, 13 May 2025 22:50:59 -0400 Subject: [PATCH 4/4] Refactor, fix and update tests --- packages/core/solidity/src/governor.test.ts | 2 +- .../core/solidity/src/governor.test.ts.md | 8 +- .../core/solidity/src/governor.test.ts.snap | Bin 2385 -> 2349 bytes packages/core/solidity/src/governor.ts | 4 +- packages/core/solidity/src/set-upgradeable.ts | 74 ++++++------------ 5 files changed, 30 insertions(+), 58 deletions(-) diff --git a/packages/core/solidity/src/governor.test.ts b/packages/core/solidity/src/governor.test.ts index 8b84b468c..3d7535024 100644 --- a/packages/core/solidity/src/governor.test.ts +++ b/packages/core/solidity/src/governor.test.ts @@ -162,6 +162,6 @@ test('API assert defaults', async t => { }); test('API isAccessControlRequired', async t => { - t.is(governor.isAccessControlRequired({ upgradeable: 'uups' }), true); + t.is(governor.isAccessControlRequired({ upgradeable: 'uups' }), false); t.is(governor.isAccessControlRequired({}), false); }); diff --git a/packages/core/solidity/src/governor.test.ts.md b/packages/core/solidity/src/governor.test.ts.md index d3f9d9ffa..cfb1351a9 100644 --- a/packages/core/solidity/src/governor.test.ts.md +++ b/packages/core/solidity/src/governor.test.ts.md @@ -1614,17 +1614,16 @@ Generated by [AVA](https://avajs.dev). import {GovernorVotesQuorumFractionUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol";␊ import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";␊ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";␊ - import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";␊ import {TimelockControllerUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/TimelockControllerUpgradeable.sol";␊ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";␊ ␊ - contract MyGovernor is Initializable, GovernorUpgradeable, GovernorCountingSimpleUpgradeable, GovernorVotesUpgradeable, GovernorVotesQuorumFractionUpgradeable, GovernorTimelockControlUpgradeable, OwnableUpgradeable, UUPSUpgradeable {␊ + contract MyGovernor is Initializable, GovernorUpgradeable, GovernorCountingSimpleUpgradeable, GovernorVotesUpgradeable, GovernorVotesQuorumFractionUpgradeable, GovernorTimelockControlUpgradeable, UUPSUpgradeable {␊ /// @custom:oz-upgrades-unsafe-allow constructor␊ constructor() {␊ _disableInitializers();␊ }␊ ␊ - function initialize(IVotes _token, TimelockControllerUpgradeable _timelock, address initialOwner)␊ + function initialize(IVotes _token, TimelockControllerUpgradeable _timelock)␊ public initializer␊ {␊ __Governor_init("MyGovernor");␊ @@ -1632,7 +1631,6 @@ Generated by [AVA](https://avajs.dev). __GovernorVotes_init(_token);␊ __GovernorVotesQuorumFraction_init(4);␊ __GovernorTimelockControl_init(_timelock);␊ - __Ownable_init(initialOwner);␊ __UUPSUpgradeable_init();␊ }␊ ␊ @@ -1647,7 +1645,7 @@ Generated by [AVA](https://avajs.dev). function _authorizeUpgrade(address newImplementation)␊ internal␊ override␊ - onlyOwner␊ + onlyGovernance␊ {}␊ ␊ // The following functions are overrides required by Solidity.␊ diff --git a/packages/core/solidity/src/governor.test.ts.snap b/packages/core/solidity/src/governor.test.ts.snap index 1e58b118d444bd65f00d2e21e48bbe1adf1d6470..cf418a4b81f33b21c1087c07692c5980ce8b17ea 100644 GIT binary patch literal 2349 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 DWRQCD diff --git a/packages/core/solidity/src/governor.ts b/packages/core/solidity/src/governor.ts index 320050276..0fec389dd 100644 --- a/packages/core/solidity/src/governor.ts +++ b/packages/core/solidity/src/governor.ts @@ -61,8 +61,8 @@ export interface GovernorOptions extends CommonOptions { settings?: boolean; } -export function isAccessControlRequired(opts: Partial): boolean { - return opts.upgradeable === 'uups'; +export function isAccessControlRequired(_: Partial): boolean { + return false; } function withDefaults(opts: GovernorOptions): Required { diff --git a/packages/core/solidity/src/set-upgradeable.ts b/packages/core/solidity/src/set-upgradeable.ts index 682429393..bdd72198d 100644 --- a/packages/core/solidity/src/set-upgradeable.ts +++ b/packages/core/solidity/src/set-upgradeable.ts @@ -7,10 +7,13 @@ export const upgradeableOptions = [false, 'transparent', 'uups'] as const; export type Upgradeable = (typeof upgradeableOptions)[number]; - -function setupUpgradeableCommon(c: ContractBuilder, upgradeable: Upgradeable) { +function setUpgradeableBase( + c: ContractBuilder, + upgradeable: Upgradeable, + restrictAuthorizeUpgradeWhenUUPS: () => void, +) { if (upgradeable === false) { - return false; + return; } c.upgradeable = true; @@ -20,68 +23,39 @@ function setupUpgradeableCommon(c: ContractBuilder, upgradeable: Upgradeable) { path: '@openzeppelin/contracts/proxy/utils/Initializable.sol', }); - return true; -} - - -function setupUUPS(c: ContractBuilder, applyAccessControl: () => void) { - const UUPSUpgradeable = { - name: 'UUPSUpgradeable', - path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', - }; - c.addParent(UUPSUpgradeable); - c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); - - - applyAccessControl(); - - c.setFunctionBody([], functions._authorizeUpgrade); -} - -export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) { - if (!setupUpgradeableCommon(c, upgradeable)) { - return; - } - switch (upgradeable) { case 'transparent': break; case 'uups': { - setupUUPS(c, () => { - requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader'); - }); + restrictAuthorizeUpgradeWhenUUPS(); + const UUPSUpgradeable = { + name: 'UUPSUpgradeable', + path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol', + }; + c.addParent(UUPSUpgradeable); + c.addOverride(UUPSUpgradeable, functions._authorizeUpgrade); + c.setFunctionBody([], functions._authorizeUpgrade); break; } default: { - const _: never = upgradeable as Exclude; + const _: never = upgradeable; throw new Error('Unknown value for `upgradeable`'); } } } -export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) { - if (!setupUpgradeableCommon(c, upgradeable)) { - return; - } - - switch (upgradeable) { - case 'transparent': - break; - - case 'uups': { - setupUUPS(c, () => { - c.addModifier('onlyGovernance', functions._authorizeUpgrade); - }); - break; - } +export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) { + setUpgradeableBase(c, upgradeable, () => { + requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader'); + }); +} - default: { - const _: never = upgradeable as Exclude; - throw new Error('Unknown value for `upgradeable`'); - } - } +export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) { + setUpgradeableBase(c, upgradeable, () => { + c.addModifier('onlyGovernance', functions._authorizeUpgrade); + }); } const functions = defineFunctions({