Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use namespaced storage for upgradeable contracts #4534

Merged
merged 13 commits into from
Sep 11, 2023
5 changes: 5 additions & 0 deletions .changeset/wet-bears-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---

Upgradeable contracts now use namespaced storage (EIP-7201).
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ runs:
steps:
- uses: actions/setup-node@v3
with:
node-version: 14.x
node-version: 16.x
- uses: actions/cache@v3
id: cache
with:
Expand Down
6 changes: 3 additions & 3 deletions contracts/governance/Governor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
bytes[] memory calldatas,
string memory description,
address proposer
) internal virtual returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
) internal virtual returns (uint256 proposalId) {
proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));

if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) {
revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length);
Expand Down Expand Up @@ -329,7 +329,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
description
);

return proposalId;
// Using a named return variable to avoid stack too deep errors
}

/**
Expand Down
17 changes: 12 additions & 5 deletions contracts/governance/extensions/GovernorVotes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@ import {SafeCast} from "../../utils/math/SafeCast.sol";
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.
*/
abstract contract GovernorVotes is Governor {
IERC5805 public immutable token;
IERC5805 private immutable _token;

constructor(IVotes tokenAddress) {
token = IERC5805(address(tokenAddress));
_token = IERC5805(address(tokenAddress));
}

/**
* @dev The token that voting power is sourced from.
*/
function token() public view virtual returns (IERC5805) {
return _token;
}

/**
* @dev Clock (as specified in EIP-6372) is set to match the token's clock. Fallback to block numbers if the token
* does not implement EIP-6372.
*/
function clock() public view virtual override returns (uint48) {
try token.clock() returns (uint48 timepoint) {
try token().clock() returns (uint48 timepoint) {
return timepoint;
} catch {
return SafeCast.toUint48(block.number);
Expand All @@ -35,7 +42,7 @@ abstract contract GovernorVotes is Governor {
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual override returns (string memory) {
try token.CLOCK_MODE() returns (string memory clockmode) {
try token().CLOCK_MODE() returns (string memory clockmode) {
return clockmode;
} catch {
return "mode=blocknumber&from=default";
Expand All @@ -50,6 +57,6 @@ abstract contract GovernorVotes is Governor {
uint256 timepoint,
bytes memory /*params*/
) internal view virtual override returns (uint256) {
return token.getPastVotes(account, timepoint);
return token().getPastVotes(account, timepoint);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
* @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
*/
function quorum(uint256 timepoint) public view virtual override returns (uint256) {
return (token.getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator();
return (token().getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator();
}

/**
Expand Down
56 changes: 47 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
"semver": "^7.3.5",
"solhint": "^3.3.6",
"solhint-plugin-openzeppelin": "file:scripts/solhint-custom",
"solidity-ast": "^0.4.25",
"solidity-ast": "^0.4.50",
"solidity-coverage": "^0.8.0",
"solidity-docgen": "^0.6.0-beta.29",
"undici": "^5.22.1",
Expand Down
6 changes: 5 additions & 1 deletion scripts/upgradeable/transpile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ fi
# -i: use included Initializable
# -x: exclude proxy-related contracts with a few exceptions
# -p: emit public initializer
# -n: use namespaces
# -N: exclude from namespaces transformation
npx @openzeppelin/upgrade-safe-transpiler@latest -D \
-b "$build_info" \
-i contracts/proxy/utils/Initializable.sol \
Expand All @@ -32,7 +34,9 @@ npx @openzeppelin/upgrade-safe-transpiler@latest -D \
-x '!contracts/proxy/ERC1967/ERC1967Utils.sol' \
-x '!contracts/proxy/utils/UUPSUpgradeable.sol' \
-x '!contracts/proxy/beacon/IBeacon.sol' \
-p 'contracts/**/presets/**/*'
-p 'contracts/**/presets/**/*' \
-n \
-N 'contracts/mocks/**/*'

# delete compilation artifacts of vanilla code
npm run clean
Loading