Skip to content

Commit 322df42

Browse files
frangioAmxx
andcommitted
Enable partial transpilation for upgradeable package (#4628)
Co-authored-by: Hadrien Croubois <[email protected]> (cherry picked from commit 58463a9)
1 parent 4ce98d7 commit 322df42

20 files changed

+192
-49
lines changed

.changeset/grumpy-poets-rush.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'openzeppelin-solidity': major
3+
---
4+
5+
Upgradeable Contracts: No longer transpile interfaces, libraries, and stateless contracts.

.github/actions/setup/action.yml

-2
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,3 @@ runs:
1515
run: npm ci
1616
shell: bash
1717
if: steps.cache.outputs.cache-hit != 'true'
18-
env:
19-
SKIP_COMPILE: true

.github/workflows/checks.yml

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ jobs:
5656
fetch-depth: 0 # Include history so patch conflicts are resolved automatically
5757
- name: Set up environment
5858
uses: ./.github/actions/setup
59+
- name: Copy non-upgradeable contracts as dependency
60+
run:
61+
cp -rnT contracts node_modules/@openzeppelin/contracts
5962
- name: Transpile to upgradeable
6063
run: bash scripts/upgradeable/transpile.sh
6164
- name: Run tests

contracts/mocks/Stateless.sol

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
// We keep these imports and a dummy contract just to we can run the test suite after transpilation.
6+
7+
import {Address} from "../utils/Address.sol";
8+
import {Arrays} from "../utils/Arrays.sol";
9+
import {AuthorityUtils} from "../access/manager/AuthorityUtils.sol";
10+
import {Base64} from "../utils/Base64.sol";
11+
import {BitMaps} from "../utils/structs/BitMaps.sol";
12+
import {Checkpoints} from "../utils/structs/Checkpoints.sol";
13+
import {Clones} from "../proxy/Clones.sol";
14+
import {Create2} from "../utils/Create2.sol";
15+
import {DoubleEndedQueue} from "../utils/structs/DoubleEndedQueue.sol";
16+
import {ECDSA} from "../utils/cryptography/ECDSA.sol";
17+
import {EnumerableMap} from "../utils/structs/EnumerableMap.sol";
18+
import {EnumerableSet} from "../utils/structs/EnumerableSet.sol";
19+
import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
20+
import {ERC165} from "../utils/introspection/ERC165.sol";
21+
import {ERC165Checker} from "../utils/introspection/ERC165Checker.sol";
22+
import {ERC1967Utils} from "../proxy/ERC1967/ERC1967Utils.sol";
23+
import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
24+
import {Math} from "../utils/math/Math.sol";
25+
import {MerkleProof} from "../utils/cryptography/MerkleProof.sol";
26+
import {MessageHashUtils} from "../utils/cryptography/MessageHashUtils.sol";
27+
import {SafeCast} from "../utils/math/SafeCast.sol";
28+
import {SafeERC20} from "../token/ERC20/utils/SafeERC20.sol";
29+
import {ShortStrings} from "../utils/ShortStrings.sol";
30+
import {SignatureChecker} from "../utils/cryptography/SignatureChecker.sol";
31+
import {SignedMath} from "../utils/math/SignedMath.sol";
32+
import {StorageSlot} from "../utils/StorageSlot.sol";
33+
import {Strings} from "../utils/Strings.sol";
34+
import {Time} from "../utils/types/Time.sol";
35+
36+
contract Dummy1234 {}

contracts/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"!/mocks/**/*"
99
],
1010
"scripts": {
11-
"prepare": "bash ../scripts/prepare-contracts-package.sh",
11+
"prepack": "bash ../scripts/prepack.sh",
1212
"prepare-docs": "cd ..; npm run prepare-docs"
1313
},
1414
"repository": {

contracts/proxy/utils/UUPSUpgradeable.sol

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
1515
* `UUPSUpgradeable` with a custom implementation of upgrades.
1616
*
1717
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
18+
*
19+
* @custom:stateless
1820
*/
1921
abstract contract UUPSUpgradeable is IERC1822Proxiable {
2022
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable

contracts/token/ERC1155/utils/ERC1155Holder.sol

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {IERC1155Receiver} from "../IERC1155Receiver.sol";
1111
*
1212
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
1313
* stuck.
14+
*
15+
* @custom:stateless
1416
*/
1517
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
1618
/**

contracts/token/ERC721/utils/ERC721Holder.sol

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {IERC721Receiver} from "../IERC721Receiver.sol";
1111
* Accepts all token transfers.
1212
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
1313
* {IERC721-setApprovalForAll}.
14+
*
15+
* @custom:stateless
1416
*/
1517
abstract contract ERC721Holder is IERC721Receiver {
1618
/**

contracts/utils/Context.sol

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pragma solidity ^0.8.20;
1212
* is concerned).
1313
*
1414
* This contract is only required for intermediate, library-like contracts.
15+
*
16+
* @custom:stateless
1517
*/
1618
abstract contract Context {
1719
function _msgSender() internal view virtual returns (address) {

contracts/utils/Multicall.sol

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {Address} from "./Address.sol";
77

88
/**
99
* @dev Provides a function to batch together multiple calls in a single external call.
10+
*
11+
* @custom:stateless
1012
*/
1113
abstract contract Multicall {
1214
/**

contracts/utils/introspection/ERC165.sol

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {IERC165} from "./IERC165.sol";
1616
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
1717
* }
1818
* ```
19+
*
20+
* @custom:stateless
1921
*/
2022
abstract contract ERC165 is IERC165 {
2123
/**

hardhat.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ module.exports = {
9393
},
9494
},
9595
exposed: {
96+
imports: true,
9697
initializers: true,
9798
exclude: ['vendor/**/*'],
9899
},

package-lock.json

+92-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"name": "openzeppelin-solidity",
33
"description": "Secure Smart Contract library for Solidity",
44
"version": "5.0.0-rc.0",
5+
"private": true,
56
"files": [
67
"/contracts/**/*.sol",
7-
"/build/contracts/*.json",
88
"!/contracts/mocks/**/*"
99
],
1010
"scripts": {
@@ -20,7 +20,6 @@
2020
"lint:sol": "prettier --log-level warn --ignore-path .gitignore '{contracts,test}/**/*.sol' --check && solhint '{contracts,test}/**/*.sol'",
2121
"lint:sol:fix": "prettier --log-level warn --ignore-path .gitignore '{contracts,test}/**/*.sol' --write",
2222
"clean": "hardhat clean && rimraf build contracts/build",
23-
"prepare": "scripts/prepare.sh",
2423
"prepack": "scripts/prepack.sh",
2524
"generate": "scripts/generate/run.js",
2625
"release": "scripts/release/release.sh",
@@ -59,6 +58,7 @@
5958
"@nomiclabs/hardhat-web3": "^2.0.0",
6059
"@openzeppelin/docs-utils": "^0.1.4",
6160
"@openzeppelin/test-helpers": "^0.5.13",
61+
"@openzeppelin/upgrade-safe-transpiler": "^0.3.30",
6262
"@openzeppelin/upgrades-core": "^1.20.6",
6363
"array.prototype.at": "^1.1.1",
6464
"chai": "^4.2.0",
@@ -70,7 +70,7 @@
7070
"glob": "^10.3.5",
7171
"graphlib": "^2.1.8",
7272
"hardhat": "^2.9.1",
73-
"hardhat-exposed": "^0.3.11",
73+
"hardhat-exposed": "^0.3.12-1",
7474
"hardhat-gas-reporter": "^1.0.4",
7575
"hardhat-ignore-warnings": "^0.2.0",
7676
"keccak256": "^1.0.2",

scripts/prepack.sh

+14-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@ set -euo pipefail
44
shopt -s globstar
55

66
# cross platform `mkdir -p`
7-
node -e 'fs.mkdirSync("build/contracts", { recursive: true })'
7+
mkdirp() {
8+
node -e "fs.mkdirSync('$1', { recursive: true })"
9+
}
810

9-
cp artifacts/contracts/**/*.json build/contracts
10-
rm build/contracts/*.dbg.json
11+
# cd to the root of the repo
12+
cd "$(git rev-parse --show-toplevel)"
1113

14+
npm run clean
15+
16+
env COMPILE_MODE=production npm run compile
17+
18+
mkdirp contracts/build/contracts
19+
cp artifacts/contracts/**/*.json contracts/build/contracts
20+
rm contracts/build/contracts/*.dbg.json
1221
node scripts/remove-ignored-artifacts.js
22+
23+
cp README.md contracts/

scripts/prepare-contracts-package.sh

-15
This file was deleted.

scripts/prepare.sh

-10
This file was deleted.

scripts/remove-ignored-artifacts.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const ignorePatternsSubtrees = ignorePatterns
2323
.concat(ignorePatterns.map(pat => path.join(pat, '**/*')))
2424
.map(p => p.replace(/^\//, ''));
2525

26-
const artifactsDir = 'build/contracts';
26+
const artifactsDir = 'contracts/build/contracts';
2727
const buildinfo = 'artifacts/build-info';
2828
const filenames = fs.readdirSync(buildinfo);
2929

scripts/upgradeable/transpile.sh

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
set -euo pipefail -x
44

5+
VERSION="$(jq -r .version contracts/package.json)"
56
DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")"
67

78
bash "$DIRNAME/patch-apply.sh"
9+
sed -i "s/<package-version>/$VERSION/g" contracts/package.json
10+
git add contracts/package.json
811

912
npm run clean
1013
npm run compile
@@ -24,7 +27,8 @@ fi
2427
# -p: emit public initializer
2528
# -n: use namespaces
2629
# -N: exclude from namespaces transformation
27-
npx @openzeppelin/upgrade-safe-transpiler@latest -D \
30+
# -q: partial transpilation using @openzeppelin/contracts as peer project
31+
npx @openzeppelin/upgrade-safe-transpiler -D \
2832
-b "$build_info" \
2933
-i contracts/proxy/utils/Initializable.sol \
3034
-x 'contracts-exposed/**/*' \
@@ -36,7 +40,8 @@ npx @openzeppelin/upgrade-safe-transpiler@latest -D \
3640
-x '!contracts/proxy/beacon/IBeacon.sol' \
3741
-p 'contracts/**/presets/**/*' \
3842
-n \
39-
-N 'contracts/mocks/**/*'
43+
-N 'contracts/mocks/**/*' \
44+
-q '@openzeppelin/'
4045

4146
# delete compilation artifacts of vanilla code
4247
npm run clean

0 commit comments

Comments
 (0)