Skip to content

Commit 1ccba07

Browse files
elisafalkericglau
andauthored
Use onlyGovernance to restrict upgrades for Governor with UUPS (#544)
Co-authored-by: Eric Lau <ericglau@outlook.com>
1 parent 76b3ca6 commit 1ccba07

File tree

6 files changed

+33
-12
lines changed

6 files changed

+33
-12
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@openzeppelin/wizard': patch
3+
---
4+
5+
Use `onlyGovernance` to restrict upgrades for Governor with UUPS
6+
- **Potentially breaking changes**:
7+
- Governor with UUPS: `_authorizeUpgrade` function is restricted by `onlyGovernance` instead of `onlyOwner`

packages/core/solidity/src/governor.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ test('API assert defaults', async t => {
162162
});
163163

164164
test('API isAccessControlRequired', async t => {
165-
t.is(governor.isAccessControlRequired({ upgradeable: 'uups' }), true);
165+
t.is(governor.isAccessControlRequired({ upgradeable: 'uups' }), false);
166166
t.is(governor.isAccessControlRequired({}), false);
167167
});

packages/core/solidity/src/governor.test.ts.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,25 +1614,23 @@ Generated by [AVA](https://avajs.dev).
16141614
import {GovernorVotesQuorumFractionUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol";␊
16151615
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";␊
16161616
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";␊
1617-
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";␊
16181617
import {TimelockControllerUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/TimelockControllerUpgradeable.sol";␊
16191618
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";␊
16201619
1621-
contract MyGovernor is Initializable, GovernorUpgradeable, GovernorCountingSimpleUpgradeable, GovernorVotesUpgradeable, GovernorVotesQuorumFractionUpgradeable, GovernorTimelockControlUpgradeable, OwnableUpgradeable, UUPSUpgradeable {␊
1620+
contract MyGovernor is Initializable, GovernorUpgradeable, GovernorCountingSimpleUpgradeable, GovernorVotesUpgradeable, GovernorVotesQuorumFractionUpgradeable, GovernorTimelockControlUpgradeable, UUPSUpgradeable {␊
16221621
/// @custom:oz-upgrades-unsafe-allow constructor␊
16231622
constructor() {␊
16241623
_disableInitializers();␊
16251624
}␊
16261625
1627-
function initialize(IVotes _token, TimelockControllerUpgradeable _timelock, address initialOwner)␊
1626+
function initialize(IVotes _token, TimelockControllerUpgradeable _timelock)␊
16281627
public initializer␊
16291628
{␊
16301629
__Governor_init("MyGovernor");␊
16311630
__GovernorCountingSimple_init();␊
16321631
__GovernorVotes_init(_token);␊
16331632
__GovernorVotesQuorumFraction_init(4);␊
16341633
__GovernorTimelockControl_init(_timelock);␊
1635-
__Ownable_init(initialOwner);␊
16361634
__UUPSUpgradeable_init();␊
16371635
}␊
16381636
@@ -1647,7 +1645,7 @@ Generated by [AVA](https://avajs.dev).
16471645
function _authorizeUpgrade(address newImplementation)␊
16481646
internal␊
16491647
override␊
1650-
onlyOwner
1648+
onlyGovernance
16511649
{}␊
16521650
16531651
// The following functions are overrides required by Solidity.␊
-36 Bytes
Binary file not shown.

packages/core/solidity/src/governor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { OptionsError } from './error';
77
import { setAccessControl } from './set-access-control';
88
import { printContract } from './print';
99
import { setInfo } from './set-info';
10-
import { setUpgradeable } from './set-upgradeable';
10+
import { setUpgradeableGovernor } from './set-upgradeable';
1111
import { defineFunctions } from './utils/define-functions';
1212
import { durationToBlocks, durationToTimestamp } from './utils/duration';
1313
import { clockModeDefault, type ClockMode } from './set-clock-mode';
@@ -61,8 +61,8 @@ export interface GovernorOptions extends CommonOptions {
6161
settings?: boolean;
6262
}
6363

64-
export function isAccessControlRequired(opts: Partial<GovernorOptions>): boolean {
65-
return opts.upgradeable === 'uups';
64+
export function isAccessControlRequired(_: Partial<GovernorOptions>): boolean {
65+
return false;
6666
}
6767

6868
function withDefaults(opts: GovernorOptions): Required<GovernorOptions> {
@@ -99,7 +99,7 @@ export function buildGovernor(opts: GovernorOptions): Contract {
9999
addTimelock(c, allOpts);
100100

101101
setAccessControl(c, allOpts.access);
102-
setUpgradeable(c, allOpts.upgradeable, allOpts.access);
102+
setUpgradeableGovernor(c, allOpts.upgradeable);
103103
setInfo(c, allOpts.info);
104104

105105
return c;

packages/core/solidity/src/set-upgradeable.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ export const upgradeableOptions = [false, 'transparent', 'uups'] as const;
77

88
export type Upgradeable = (typeof upgradeableOptions)[number];
99

10-
export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) {
10+
function setUpgradeableBase(
11+
c: ContractBuilder,
12+
upgradeable: Upgradeable,
13+
restrictAuthorizeUpgradeWhenUUPS: () => void,
14+
) {
1115
if (upgradeable === false) {
1216
return;
1317
}
@@ -24,7 +28,7 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc
2428
break;
2529

2630
case 'uups': {
27-
requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader');
31+
restrictAuthorizeUpgradeWhenUUPS();
2832
const UUPSUpgradeable = {
2933
name: 'UUPSUpgradeable',
3034
path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol',
@@ -42,6 +46,18 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc
4246
}
4347
}
4448

49+
export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) {
50+
setUpgradeableBase(c, upgradeable, () => {
51+
requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader');
52+
});
53+
}
54+
55+
export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) {
56+
setUpgradeableBase(c, upgradeable, () => {
57+
c.addModifier('onlyGovernance', functions._authorizeUpgrade);
58+
});
59+
}
60+
4561
const functions = defineFunctions({
4662
_authorizeUpgrade: {
4763
args: [{ name: 'newImplementation', type: 'address' }],

0 commit comments

Comments
 (0)