From 2602160604c365a63369d96249edc43d4b0558d4 Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Wed, 7 Aug 2024 15:17:37 +0200 Subject: [PATCH 01/20] feat: refactor upgradable interface --- .github/workflows/ci.yml | 17 + .../scripts/deploy-factory-uups.ts | 2 +- examples/upgradable-example-l1/.eslintrc.js | 7 + .../.openzeppelin/sepolia.json | 338 +++++++++++++++++ examples/upgradable-example-l1/README.md | 67 ++++ .../upgradable-example-l1/contracts/Box.sol | 27 ++ .../contracts/BoxUups.sol | 33 ++ .../contracts/BoxUupsV2.sol | 54 +++ .../upgradable-example-l1/contracts/BoxV2.sol | 51 +++ .../contracts/Greeter.sol | 16 + .../upgradable-example-l1/hardhat.config.ts | 35 ++ examples/upgradable-example-l1/package.json | 53 +++ .../scripts/deploy-box-beacon.ts | 18 + .../scripts/deploy-box-proxy.ts | 13 + .../scripts/deploy-box-uups.ts | 13 + .../scripts/upgrade-box-beacon.ts | 22 ++ .../scripts/upgrade-box-uups.ts | 17 + .../scripts/upgrade-box.ts | 18 + examples/upgradable-example-l1/tsconfig.json | 18 + examples/upgradable-example/hardhat.config.ts | 3 +- examples/upgradable-example/package.json | 13 +- .../scripts/deploy-box-beacon-factory.ts | 39 ++ .../scripts/deploy-box-beacon.ts | 6 +- .../scripts/deploy-box-proxy-factory.ts | 29 ++ .../scripts/deploy-box-proxy.ts | 2 +- .../scripts/deploy-box-uups-factory.ts | 29 ++ .../scripts/deploy-box-uups.ts | 2 +- .../scripts/upgrade-box-beacon-factory.ts | 54 +++ .../scripts/upgrade-box-beacon.ts | 8 +- .../scripts/upgrade-box-factory.ts | 35 ++ .../scripts/upgrade-box-uups.ts | 4 +- .../upgradable-example/scripts/upgrade-box.ts | 5 +- .../hardhat-zksync-upgradable/package.json | 18 +- .../hardhat-zksync-upgradable/src/index.ts | 203 ++++++++-- .../src/interfaces.ts | 88 ++++- packages/hardhat-zksync-upgradable/src/log.ts | 32 ++ .../hardhat-zksync-upgradable/src/plugin.ts | 13 +- .../proxy-deployment/deploy-beacon-proxy.ts | 217 ++++++----- .../src/proxy-deployment/deploy-beacon.ts | 133 +++++-- .../src/proxy-deployment/deploy-proxy.ts | 248 ++++++++----- .../src/proxy-upgrade/upgrade-beacon.ts | 124 +++++-- .../src/proxy-upgrade/upgrade-proxy.ts | 179 +++++---- .../src/type-extensions.ts | 6 +- .../src/utils/utils-general.ts | 14 + pnpm-lock.yaml | 347 ++++++++++++++++++ 45 files changed, 2244 insertions(+), 426 deletions(-) create mode 100644 examples/upgradable-example-l1/.eslintrc.js create mode 100644 examples/upgradable-example-l1/.openzeppelin/sepolia.json create mode 100644 examples/upgradable-example-l1/README.md create mode 100644 examples/upgradable-example-l1/contracts/Box.sol create mode 100644 examples/upgradable-example-l1/contracts/BoxUups.sol create mode 100644 examples/upgradable-example-l1/contracts/BoxUupsV2.sol create mode 100644 examples/upgradable-example-l1/contracts/BoxV2.sol create mode 100644 examples/upgradable-example-l1/contracts/Greeter.sol create mode 100644 examples/upgradable-example-l1/hardhat.config.ts create mode 100644 examples/upgradable-example-l1/package.json create mode 100644 examples/upgradable-example-l1/scripts/deploy-box-beacon.ts create mode 100644 examples/upgradable-example-l1/scripts/deploy-box-proxy.ts create mode 100644 examples/upgradable-example-l1/scripts/deploy-box-uups.ts create mode 100644 examples/upgradable-example-l1/scripts/upgrade-box-beacon.ts create mode 100644 examples/upgradable-example-l1/scripts/upgrade-box-uups.ts create mode 100644 examples/upgradable-example-l1/scripts/upgrade-box.ts create mode 100644 examples/upgradable-example-l1/tsconfig.json create mode 100644 examples/upgradable-example/scripts/deploy-box-beacon-factory.ts create mode 100644 examples/upgradable-example/scripts/deploy-box-proxy-factory.ts create mode 100644 examples/upgradable-example/scripts/deploy-box-uups-factory.ts create mode 100644 examples/upgradable-example/scripts/upgrade-box-beacon-factory.ts create mode 100644 examples/upgradable-example/scripts/upgrade-box-factory.ts create mode 100644 packages/hardhat-zksync-upgradable/src/log.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58e4e3a5e..441eddf14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -191,6 +191,23 @@ jobs: pnpm hardhat run scripts/deploy-box-uups.ts pnpm hardhat run scripts/upgrade-box-beacon.ts pnpm hardhat run scripts/upgrade-box-uups.ts + pnpm hardhat run scripts/upgrade-box.ts + pnpm hardhat run scripts/deploy-box-beacon-factory.ts + pnpm hardhat run scripts/deploy-box-proxy-factory.ts + pnpm hardhat run scripts/deploy-box-uups-factory.ts + pnpm hardhat run scripts/upgrade-box-beacon-factory.ts + pnpm hardhat run scripts/upgrade-box-uups-factory.ts + pnpm hardhat run scripts/upgrade-box-factory.ts + + - name: Test upgradable example + run: | + cd examples/upgradable-example-l1 + pnpm hardhat compile + pnpm hardhat run scripts/deploy-box-beacon.ts + pnpm hardhat run scripts/deploy-box-proxy.ts + pnpm hardhat run scripts/deploy-box-uups.ts + pnpm hardhat run scripts/upgrade-box-beacon.ts + pnpm hardhat run scripts/upgrade-box-uups.ts pnpm hardhat run scripts/upgrade-box.ts - name: Test zksync-ethers example diff --git a/e2e/fixture-projects/compatability-check/scripts/deploy-factory-uups.ts b/e2e/fixture-projects/compatability-check/scripts/deploy-factory-uups.ts index b87090d90..98bbaa4d5 100644 --- a/e2e/fixture-projects/compatability-check/scripts/deploy-factory-uups.ts +++ b/e2e/fixture-projects/compatability-check/scripts/deploy-factory-uups.ts @@ -24,7 +24,7 @@ async function main() { 'Something went wrong during deployment of a Factory contract. Initialize functions is probably not called.', ); } - console.info("Successfully deployed upgradable factor contract.") + console.info("Successfully deployed upgradable factory contract.") } main().catch((error) => { diff --git a/examples/upgradable-example-l1/.eslintrc.js b/examples/upgradable-example-l1/.eslintrc.js new file mode 100644 index 000000000..49bafd11a --- /dev/null +++ b/examples/upgradable-example-l1/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: [`${__dirname}/../../config/eslint/eslintrc.cjs`], + parserOptions: { + project: `${__dirname}/tsconfig.json`, + sourceType: "module", + }, +}; diff --git a/examples/upgradable-example-l1/.openzeppelin/sepolia.json b/examples/upgradable-example-l1/.openzeppelin/sepolia.json new file mode 100644 index 000000000..071b8fa9f --- /dev/null +++ b/examples/upgradable-example-l1/.openzeppelin/sepolia.json @@ -0,0 +1,338 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0xE8a5dD63426D1C05B16ecd4D950C7E7BA5420Fe1", + "txHash": "0x663597fdbe68f11c887330a0e7d6fb432130e1b3fddf8b4838a338816bb03d76", + "kind": "beacon" + }, + { + "address": "0xA48677C93eB9D3B62cc5FE54C63a6B64Cc64A5f6", + "txHash": "0x6ef386d245e39b307cffcd4bf98ee1775ab4ba1fdf4d353c6305e06a8a945738", + "kind": "transparent" + }, + { + "address": "0xA4f938Ba130956467aC5D9D9424dc1c67508d7AB", + "txHash": "0x1d9447ba1235c1e715033d2aadf07f1d927d9dde2473d9197479ee98ec97a742", + "kind": "uups" + }, + { + "address": "0xfa83abe364c47196E24Bc1A9ed537d62Cf30Cf9F", + "txHash": "0x76b73c7c6916dd4c6f61ce129d7ac4a09e00c9544688ac225506444cb214d8e9", + "kind": "beacon" + }, + { + "address": "0xEaB1F8a85c0bF6Bc047D7F2251485216cb38BC23", + "txHash": "0xbeff40e65090150a7a2b5dd32dee19c3ce750acd16ac5968077fcc93cc089efa", + "kind": "transparent" + }, + { + "address": "0x4e9282a22189Cb2dFAd28D1e2277Ab4A6A7F79B9", + "txHash": "0x169c71730bce649106702513d53cb2d9976901b5a7449f89935fcf26eaf6b209", + "kind": "transparent" + }, + { + "address": "0x1DEe5f4D6b9bc71CD79d0f1780451f2f7Ae85C9e", + "txHash": "0x5c9a1e4027f02d7f171f2da1d9f9e06e705f4d26c3e4c7720b54c4445aee96b6", + "kind": "uups" + }, + { + "address": "0x925bc6D3A26F28fD960e3Da2CF8f19524dEC8DC7", + "txHash": "0x2fab0ec9f872881549c39f4b56a2d485d57978e30ef80f33185935a222838a6d", + "kind": "uups" + }, + { + "address": "0x74EF4793372F97D0b4F1c2208BF0D72cf0F96f5C", + "txHash": "0x647c4741baceb72d75e14fcb2598ed6b15e67ebaabdeb21aa23f409773d1d439", + "kind": "uups" + } + ], + "impls": { + "bf966385854e3ede49da805ebbde0f3e9f882e4ba662ad33879278ae7fbfd484": { + "address": "0xA48cE32F2e6964EAADC4ED3af50A2a7E37599A87", + "txHash": "0xf3c5e2b3791e7376c42765c7e53409fd57ac2b6a02506677a8d48f4f9f836a1e", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "contract": "Box", + "label": "value", + "type": "t_uint256", + "src": "contracts/Box.sol:7" + }, + { + "contract": "Box", + "label": "secondValue", + "type": "t_uint256", + "src": "contracts/Box.sol:8" + }, + { + "contract": "Box", + "label": "thirdValue", + "type": "t_uint256", + "src": "contracts/Box.sol:9" + } + ], + "types": { + "t_uint256": { + "label": "uint256" + }, + "t_uint8": { + "label": "uint8" + }, + "t_bool": { + "label": "bool" + } + }, + "namespaces": {} + } + }, + "90ddd0edfad2f9b7b3f66d0ec849d08c6cc48df12f23635e4e48bc017aceeb5e": { + "address": "0x8F59dbBc201951C61d38d507d7bEdFC50127B06e", + "txHash": "0xa2a6726ed6a8059c286f4d540443fd3d548a694567987b8013460e582c5ec004", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "contract": "ERC1967UpgradeUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "contract": "UUPSUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "contract": "OwnableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "contract": "BoxUups", + "label": "value", + "type": "t_uint256", + "src": "contracts/BoxUups.sol:8" + }, + { + "contract": "BoxUups", + "label": "secondValue", + "type": "t_uint256", + "src": "contracts/BoxUups.sol:9" + }, + { + "contract": "BoxUups", + "label": "thirdValue", + "type": "t_uint256", + "src": "contracts/BoxUups.sol:10" + } + ], + "types": { + "t_uint256": { + "label": "uint256" + }, + "t_address": { + "label": "address" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + }, + "t_bool": { + "label": "bool" + } + }, + "namespaces": {} + } + }, + "1786c31e6c8dd2320e37d96de50ff21bb880be3012ed8e01f26ceaaecd374176": { + "address": "0x6ee4960EeEe6c4Cb4ebA4eE08c27c2F693Da5017", + "txHash": "0x30005acfaaba243551cc990b852f3971ef7138407e1b4b12d225c7bfeb92a1e8", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "contract": "BoxV2", + "label": "value", + "type": "t_uint256", + "src": "contracts/BoxV2.sol:7" + }, + { + "contract": "BoxV2", + "label": "secondValue", + "type": "t_uint256", + "src": "contracts/BoxV2.sol:8" + }, + { + "contract": "BoxV2", + "label": "thirdValue", + "type": "t_uint256", + "src": "contracts/BoxV2.sol:9" + } + ], + "types": { + "t_uint256": { + "label": "uint256" + }, + "t_uint8": { + "label": "uint8" + }, + "t_bool": { + "label": "bool" + } + }, + "namespaces": {} + } + }, + "c3202b9d264d74d50b5eea6eb203c1ae77d1e016958eb45bb06d48aeddadd823": { + "address": "0x3f3f76Dd75A55A30Af613c50318204f68E50Fe3B", + "txHash": "0xfba17a817fcd11dcb98c4478df8d0e2b41a92ea2a3238b82d98029204b8500d4", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "contract": "ERC1967UpgradeUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "contract": "UUPSUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "contract": "OwnableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "contract": "BoxUupsV2", + "label": "value", + "type": "t_uint256", + "src": "contracts/BoxUupsV2.sol:8" + }, + { + "contract": "BoxUupsV2", + "label": "secondValue", + "type": "t_uint256", + "src": "contracts/BoxUupsV2.sol:9" + }, + { + "contract": "BoxUupsV2", + "label": "thirdValue", + "type": "t_uint256", + "src": "contracts/BoxUupsV2.sol:10" + } + ], + "types": { + "t_uint256": { + "label": "uint256" + }, + "t_address": { + "label": "address" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + }, + "t_bool": { + "label": "bool" + } + }, + "namespaces": {} + } + } + } +} diff --git a/examples/upgradable-example-l1/README.md b/examples/upgradable-example-l1/README.md new file mode 100644 index 000000000..d34c061d2 --- /dev/null +++ b/examples/upgradable-example-l1/README.md @@ -0,0 +1,67 @@ +# ZKsync Era upgradable example + +This project demonstrates how to compile and deploy upgradable smart contracts in ZKsync Era using the Hardhat plugins. + +## Prerequisites + +- node.js 14.x or later. +- yarn. + +## Configuration + +Plugin configuration is located in [`hardhat.config.ts`](./hardhat.config.ts). +You should only change the ZKsync network configuration. + +`hardhat.config.ts` example with ZKsync network configured with the name `zkTestnet` and `sepolia` used as the underlying layer 1 network: +```ts +import '@matterlabs/hardhat-zksync-solc'; +import '@matterlabs/hardhat-zksync-deploy'; +import '@matterlabs/hardhat-zksync-upgradable'; + +import { HardhatUserConfig } from 'hardhat/types'; + +const config: HardhatUserConfig = { + networks: { + sepolia: { + url: 'https://sepolia.infura.io/v3/' // you can use either the URL of the Ethereum Web3 RPC, or the identifier of the network (e.g. `mainnet` or `rinkeby`) + }, + zkTestnet: { + url: 'https://sepolia.era.zksync.dev', // you should use the URL of the ZKsync network RPC + ethNetwork: 'sepolia', + zksync: true + }, + } +}; + +export default config; +``` + +If you don't specify ZKsync network (`--network`), `local-setup` with (Ethereum RPC URL) and (ZKsync RPC URL) will be used. + +## Usage + +Before using plugins, you need to build them first + +```sh +# Run the following in the *root* of the repo. +yarn +yarn build +``` + +After that you should be able to run plugins: + +```sh +# Run the following in `examples/upgradable-example` folder. +yarn +yarn hardhat compile +``` + +- `yarn hardhat compile`: compiles all the contracts in the `contracts` folder. + +To run a specific end-to-end script in the `scripts` folder, use the following command + +``` +yarn hardhat run ./scripts/ +``` + +- Example: `yarn hardhat run ./scripts/deploy-box-proxy.ts` \ No newline at end of file diff --git a/examples/upgradable-example-l1/contracts/Box.sol b/examples/upgradable-example-l1/contracts/Box.sol new file mode 100644 index 000000000..2c95bac7a --- /dev/null +++ b/examples/upgradable-example-l1/contracts/Box.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +contract Box is Initializable { + uint256 private value; + uint256 private secondValue; + uint256 private thirdValue; + + function initialize(uint256 initValue) public initializer { + value = initValue; + } + + // Reads the last stored value + function retrieve() public view returns (uint256) { + return value; + } + + // Stores a new value in the contract + function store(uint256 newValue) public { + value = newValue; + emit ValueChanged(newValue); + } + // Emitted when the stored value changes + event ValueChanged(uint256 newValue); +} diff --git a/examples/upgradable-example-l1/contracts/BoxUups.sol b/examples/upgradable-example-l1/contracts/BoxUups.sol new file mode 100644 index 000000000..0b3345dd7 --- /dev/null +++ b/examples/upgradable-example-l1/contracts/BoxUups.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; +import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; + +contract BoxUups is Initializable, UUPSUpgradeable, OwnableUpgradeable { + uint256 private value; + uint256 private secondValue; + uint256 private thirdValue; + + function initialize(uint256 initValue) public initializer { + value = initValue; + __Ownable_init(); + __UUPSUpgradeable_init(); + } + + // Reads the last stored value + function retrieve() public view returns (uint256) { + return value; + } + + // Stores a new value in the contract + function store(uint256 newValue) public { + value = newValue; + emit ValueChanged(newValue); + } + + function _authorizeUpgrade(address) internal override onlyOwner {} + + // Emitted when the stored value changes + event ValueChanged(uint256 newValue); +} diff --git a/examples/upgradable-example-l1/contracts/BoxUupsV2.sol b/examples/upgradable-example-l1/contracts/BoxUupsV2.sol new file mode 100644 index 000000000..3ae876bf9 --- /dev/null +++ b/examples/upgradable-example-l1/contracts/BoxUupsV2.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; +import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; + +contract BoxUupsV2 is Initializable, UUPSUpgradeable, OwnableUpgradeable { + uint256 private value; + uint256 private secondValue; + uint256 private thirdValue; + + function initialize(uint256 initValue) public initializer { + value = initValue; + } + + // Reads the last stored value and returns it with a prefix + function retrieve() public view returns (string memory) { + return string(abi.encodePacked('V2: ', uint2str(value))); + } + + // Converts a uint to a string + function uint2str(uint _i) internal pure returns (string memory) { + if (_i == 0) { + return '0'; + } + uint j = _i; + uint len; + while (j != 0) { + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len; + while (_i != 0) { + k = k - 1; + uint8 temp = (48 + uint8(_i - (_i / 10) * 10)); + bytes1 b1 = bytes1(temp); + bstr[k] = b1; + _i /= 10; + } + return string(bstr); + } + + // Stores a new value in the contract + function store(uint256 newValue) public { + value = newValue; + emit ValueChanged(newValue); + } + + function _authorizeUpgrade(address) internal override onlyOwner {} + + // Emitted when the stored value changes + event ValueChanged(uint256 newValue); +} diff --git a/examples/upgradable-example-l1/contracts/BoxV2.sol b/examples/upgradable-example-l1/contracts/BoxV2.sol new file mode 100644 index 000000000..d451cb8d7 --- /dev/null +++ b/examples/upgradable-example-l1/contracts/BoxV2.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +contract BoxV2 is Initializable{ + uint256 private value; + uint256 private secondValue; + uint256 private thirdValue; + + // Emitted when the stored value changes + event ValueChanged(uint256 newValue); + + function initialize(uint256 initValue) public initializer { + value = initValue; + } + + // Stores a new value in the contract + function store(uint256 newValue) public { + value = newValue; + emit ValueChanged(newValue); + } + + // Reads the last stored value and returns it with a prefix + function retrieve() public view returns (string memory) { + return string(abi.encodePacked("V2: ", uint2str(value))); + } + + // Converts a uint to a string + function uint2str(uint _i) internal pure returns (string memory) { + if (_i == 0) { + return "0"; + } + uint j = _i; + uint len; + while (j != 0) { + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len; + while (_i != 0) { + k = k - 1; + uint8 temp = (48 + uint8(_i - (_i / 10) * 10)); + bytes1 b1 = bytes1(temp); + bstr[k] = b1; + _i /= 10; + } + return string(bstr); + } +} diff --git a/examples/upgradable-example-l1/contracts/Greeter.sol b/examples/upgradable-example-l1/contracts/Greeter.sol new file mode 100644 index 000000000..0c86c024b --- /dev/null +++ b/examples/upgradable-example-l1/contracts/Greeter.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; +pragma abicoder v2; + +contract Greeter { + string greeting; + + function greet() public view returns (string memory) { + return greeting; + } + + function setGreeting(string memory _greeting) public { + greeting = _greeting; + } +} diff --git a/examples/upgradable-example-l1/hardhat.config.ts b/examples/upgradable-example-l1/hardhat.config.ts new file mode 100644 index 000000000..55a50da37 --- /dev/null +++ b/examples/upgradable-example-l1/hardhat.config.ts @@ -0,0 +1,35 @@ +import '@matterlabs/hardhat-zksync-upgradable'; +import "@nomicfoundation/hardhat-ethers" + +import { HardhatUserConfig } from 'hardhat/config'; + +const config: HardhatUserConfig = { + zksolc: { + version: 'latest', + compilerSource: 'binary', + settings: { + optimizer: { + enabled: true, + }, + }, + }, + networks: { + hardhat: { + zksync: false, + }, + eth: { + zksync: true, + url: 'http://0.0.0.0:8545', + }, + zkSyncNetwork: { + zksync: true, + ethNetwork: 'eth', + url: 'http://0.0.0.0:3050', + }, + }, + solidity: { + version: '0.8.20', + }, +}; + +export default config; diff --git a/examples/upgradable-example-l1/package.json b/examples/upgradable-example-l1/package.json new file mode 100644 index 000000000..f4252c0f7 --- /dev/null +++ b/examples/upgradable-example-l1/package.json @@ -0,0 +1,53 @@ +{ + "name": "hardhat-zksync-upgradable-example", + "version": "0.1.0", + "author": "Matter Labs", + "license": "MIT", + "scripts": { + "lint": "pnpm eslint", + "prettier:check": "pnpm prettier --check", + "lint:fix": "pnpm eslint --fix", + "fmt": "pnpm prettier --write", + "eslint": "eslint scripts/*.ts", + "prettier": "prettier scripts/*.ts", + "test": "mocha test/tests.ts --exit", + "build": "tsc --build .", + "clean": "rimraf dist" + }, + "devDependencies": { + "@openzeppelin/contracts": "^4.9.2", + "@types/node": "^18.11.17", + "@typescript-eslint/eslint-plugin": "6.13.1", + "@typescript-eslint/parser": "6.13.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-no-only-tests": "^3.1.0", + "eslint-plugin-prettier": "^5.0.1", + "prettier": "^3.3.0", + "rimraf": "^5.0.7", + "ts-node": "^10.9.2", + "typescript": "^5.3.0" + }, + "dependencies": { + "@matterlabs/hardhat-zksync-deploy": "workspace:^", + "@matterlabs/hardhat-zksync-ethers": "workspace:^", + "@matterlabs/hardhat-zksync-solc": "workspace:^", + "@matterlabs/hardhat-zksync-upgradable": "workspace:^", + "@matterlabs/hardhat-zksync-verify": "workspace:^", + "@nomicfoundation/hardhat-ethers": "3.0.6", + "@openzeppelin/contracts-upgradeable": "^4.9.2", + "chalk": "^4.1.2", + "ethers": "^6.12.2", + "hardhat": "^2.22.5", + "zksync": "^0.13.1", + "zksync-ethers": "^6.8.0" + }, + "prettier": { + "tabWidth": 4, + "printWidth": 120, + "parser": "typescript", + "singleQuote": true, + "bracketSpacing": true + } +} diff --git a/examples/upgradable-example-l1/scripts/deploy-box-beacon.ts b/examples/upgradable-example-l1/scripts/deploy-box-beacon.ts new file mode 100644 index 000000000..cada887d7 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/deploy-box-beacon.ts @@ -0,0 +1,18 @@ +import { Wallet } from 'ethers'; +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("Box"); + const box = await hre.upgrades.deployBeacon(Box); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) + + const boxBeaconProxy = await hre.upgrades.deployBeaconProxy(box, Box, [42]); + await boxBeaconProxy.waitForDeployment(); + console.info("Box Beacon Proxy deployed address: " + await boxBeaconProxy.getAddress()) +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/scripts/deploy-box-proxy.ts b/examples/upgradable-example-l1/scripts/deploy-box-proxy.ts new file mode 100644 index 000000000..facd0ec48 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/deploy-box-proxy.ts @@ -0,0 +1,13 @@ +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("Box"); + const box = await hre.upgrades.deployProxy(Box,[42]); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/scripts/deploy-box-uups.ts b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts new file mode 100644 index 000000000..e660872e4 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts @@ -0,0 +1,13 @@ +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("BoxUups"); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize'}); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/scripts/upgrade-box-beacon.ts b/examples/upgradable-example-l1/scripts/upgrade-box-beacon.ts new file mode 100644 index 000000000..d96789522 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/upgrade-box-beacon.ts @@ -0,0 +1,22 @@ +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("Box"); + const box = await hre.upgrades.deployBeacon(Box); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) + + const boxBeaconProxy = await hre.upgrades.deployBeaconProxy(box, Box, [42]); + await boxBeaconProxy.waitForDeployment(); + console.info("Box Beacon Proxy deployed address: " + await boxBeaconProxy.getAddress()) + + const BoxV2 = await hre.ethers.getContractFactory("BoxV2"); + const boxV2 = await hre.upgrades.upgradeBeacon(await box.getAddress(),BoxV2) + console.info("Box V2 address: " + await boxV2.getAddress()) + +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts new file mode 100644 index 000000000..902084bc1 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts @@ -0,0 +1,17 @@ +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("BoxUups"); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize'}); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) + + const BoxUupsV2 = await hre.ethers.getContractFactory("BoxUupsV2"); + const boxUupsV2 = await hre.upgrades.upgradeProxy(await box.getAddress(),BoxUupsV2) + console.info("Box UUps V2 address: " + await boxUupsV2.getAddress()) +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/scripts/upgrade-box.ts b/examples/upgradable-example-l1/scripts/upgrade-box.ts new file mode 100644 index 000000000..49256f4a7 --- /dev/null +++ b/examples/upgradable-example-l1/scripts/upgrade-box.ts @@ -0,0 +1,18 @@ +import * as hre from 'hardhat'; + +async function main() { + const Box = await hre.ethers.getContractFactory("Box"); + const box = await hre.upgrades.deployProxy(Box,[42]); + await box.waitForDeployment() + console.info("Box deployed address: " + await box.getAddress()) + + const BoxV2 = await hre.ethers.getContractFactory("BoxV2"); + const boxV2 = await hre.upgrades.upgradeProxy(await box.getAddress(),BoxV2) + console.info("Box V2 address: " + await boxV2.getAddress()) + +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example-l1/tsconfig.json b/examples/upgradable-example-l1/tsconfig.json new file mode 100644 index 000000000..2b2998046 --- /dev/null +++ b/examples/upgradable-example-l1/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "outDir": "dist" + }, + "include": [ + "./hardhat.config.ts", + "./scripts", + "scripts", + "./test", + "typechain/**/*" + ] +} diff --git a/examples/upgradable-example/hardhat.config.ts b/examples/upgradable-example/hardhat.config.ts index c87959898..0b0f82983 100644 --- a/examples/upgradable-example/hardhat.config.ts +++ b/examples/upgradable-example/hardhat.config.ts @@ -2,6 +2,8 @@ import '@matterlabs/hardhat-zksync-solc'; import '@matterlabs/hardhat-zksync-deploy'; import '@matterlabs/hardhat-zksync-verify'; import '@matterlabs/hardhat-zksync-upgradable'; +import '@matterlabs/hardhat-zksync-ethers'; +import "@nomicfoundation/hardhat-ethers" import { HardhatUserConfig } from 'hardhat/config'; @@ -15,7 +17,6 @@ const config: HardhatUserConfig = { }, }, }, - defaultNetwork:'zkSyncNetwork', networks: { hardhat: { zksync: true, diff --git a/examples/upgradable-example/package.json b/examples/upgradable-example/package.json index 2cf033a0d..a3c6078f2 100644 --- a/examples/upgradable-example/package.json +++ b/examples/upgradable-example/package.json @@ -30,16 +30,19 @@ "typescript": "^5.3.0" }, "dependencies": { - "ethers": "^6.12.2", - "zksync-ethers": "^6.8.0", - "hardhat": "^2.22.5", "@matterlabs/hardhat-zksync-deploy": "workspace:^", + "@matterlabs/hardhat-zksync-ethers": "workspace:^", "@matterlabs/hardhat-zksync-solc": "workspace:^", "@matterlabs/hardhat-zksync-upgradable": "workspace:^", "@matterlabs/hardhat-zksync-verify": "workspace:^", - "chalk": "^4.1.2", + "@nomicfoundation/hardhat-ethers": "3.0.6", "@openzeppelin/contracts-upgradeable": "^4.9.2", - "zksync": "^0.13.1" + "@openzeppelin/hardhat-upgrades": "^3.2.1", + "chalk": "^4.1.2", + "ethers": "^6.12.2", + "hardhat": "^2.22.5", + "zksync": "^0.13.1", + "zksync-ethers": "^6.8.0" }, "prettier": { "tabWidth": 4, diff --git a/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts b/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts new file mode 100644 index 000000000..88f30f2d2 --- /dev/null +++ b/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts @@ -0,0 +1,39 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import chalk from 'chalk'; + +import * as hre from 'hardhat'; + +async function main() { + const contractName = 'Box'; + console.info(chalk.yellow(`Deploying ${contractName}...`)); + + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + + const deployer = new Deployer(hre, zkWallet); + + const boxFactory = await hre.zksyncEthers.getContractFactory('Box', deployer.zkWallet); + const boxArtifact = await hre.deployer.loadArtifact('Box'); + + const beacon = await hre.upgrades.deployBeacon(boxFactory); + await beacon.waitForDeployment(); + + const box = await hre.upgrades.deployBeaconProxy( + deployer.zkWallet, + await beacon.getAddress(), + boxArtifact, + [42], + {}, + ); + await box.waitForDeployment(); + + box.connect(zkWallet); + const value = await box.retrieve(); + console.info(chalk.cyan('Box value is: ', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example/scripts/deploy-box-beacon.ts b/examples/upgradable-example/scripts/deploy-box-beacon.ts index 656c178fb..fd16ae2e4 100644 --- a/examples/upgradable-example/scripts/deploy-box-beacon.ts +++ b/examples/upgradable-example/scripts/deploy-box-beacon.ts @@ -7,17 +7,15 @@ import * as hre from 'hardhat'; async function main() { const contractName = 'Box'; console.info(chalk.yellow(`Deploying ${contractName}...`)); - const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; const zkWallet = Wallet.fromMnemonic(testMnemonic); const deployer = new Deployer(hre, zkWallet); - const boxContract = await deployer.loadArtifact(contractName); - const beacon = await hre.zkUpgrades.deployBeacon(deployer.zkWallet, boxContract); + const beacon = await hre.upgrades.deployBeacon(deployer.zkWallet, boxContract); await beacon.waitForDeployment(); - const box = await hre.zkUpgrades.deployBeaconProxy(deployer.zkWallet, await beacon.getAddress(), boxContract, [42]); + const box = await hre.upgrades.deployBeaconProxy(deployer.zkWallet, await beacon.getAddress(), boxContract, [42]); await box.waitForDeployment(); box.connect(zkWallet); diff --git a/examples/upgradable-example/scripts/deploy-box-proxy-factory.ts b/examples/upgradable-example/scripts/deploy-box-proxy-factory.ts new file mode 100644 index 000000000..efc5f2ea6 --- /dev/null +++ b/examples/upgradable-example/scripts/deploy-box-proxy-factory.ts @@ -0,0 +1,29 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import chalk from 'chalk'; + +import * as hre from 'hardhat'; + +async function main() { + const contractName = 'Box'; + console.info(chalk.yellow(`Deploying ${contractName}...`)); + + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + + const deployer = new Deployer(hre, zkWallet); + + const boxFactory = await hre.zksyncEthers.getContractFactory('Box', deployer.zkWallet); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'store' }); + + await box.waitForDeployment(); + + box.connect(zkWallet); + const value = await box.retrieve(); + console.info(chalk.cyan('Box value is: ', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example/scripts/deploy-box-proxy.ts b/examples/upgradable-example/scripts/deploy-box-proxy.ts index 759093fb0..15d766f71 100644 --- a/examples/upgradable-example/scripts/deploy-box-proxy.ts +++ b/examples/upgradable-example/scripts/deploy-box-proxy.ts @@ -14,7 +14,7 @@ async function main() { const deployer = new Deployer(hre, zkWallet); const contract = await deployer.loadArtifact(contractName); - const box = await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'store' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'store' }); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/deploy-box-uups-factory.ts b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts new file mode 100644 index 000000000..60e83b649 --- /dev/null +++ b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts @@ -0,0 +1,29 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import chalk from 'chalk'; + +import * as hre from 'hardhat'; + +async function main() { + const contractName = 'BoxUups'; + console.info(chalk.yellow(`Deploying ${contractName}...`)); + + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + + const deployer = new Deployer(hre, zkWallet); + + const boxFactory = await hre.zksyncEthers.getContractFactory('BoxUups', deployer.zkWallet); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize' }); + + await box.waitForDeployment(); + + box.connect(zkWallet); + const value = await box.retrieve(); + console.info(chalk.cyan('Box value is: ', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example/scripts/deploy-box-uups.ts b/examples/upgradable-example/scripts/deploy-box-uups.ts index a96dd4258..c7c70881d 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups.ts @@ -14,7 +14,7 @@ async function main() { const deployer = new Deployer(hre, zkWallet); const contract = await deployer.loadArtifact(contractName); - const box = await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/upgrade-box-beacon-factory.ts b/examples/upgradable-example/scripts/upgrade-box-beacon-factory.ts new file mode 100644 index 000000000..b1c0d34d9 --- /dev/null +++ b/examples/upgradable-example/scripts/upgrade-box-beacon-factory.ts @@ -0,0 +1,54 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import * as zk from 'zksync-ethers'; +import chalk from 'chalk'; +import * as hre from 'hardhat'; +import { Contract } from 'ethers'; + +async function main() { + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + const deployer = new Deployer(hre, zkWallet); + + // deploy beacon proxy + + const contractName = 'Box'; + const boxFactory = await hre.zksyncEthers.getContractFactory(contractName, deployer.zkWallet); + const boxArtifact = await hre.deployer.loadArtifact('Box'); + const beacon = await hre.upgrades.deployBeacon(boxFactory); + await beacon.waitForDeployment(); + + const beaconAddress = await beacon.getAddress(); + const boxBeaconProxy = await hre.upgrades.deployBeaconProxy( + deployer.zkWallet, + beaconAddress, + boxArtifact, + [42], + {}, + ); + await boxBeaconProxy.waitForDeployment(); + + // upgrade beacon + + const boxV2Artifact = await hre.deployer.loadArtifact('BoxV2'); + await hre.upgrades.upgradeBeacon(deployer.zkWallet, beaconAddress, boxV2Artifact); + console.info(chalk.green('Successfully upgraded beacon Box to BoxV2 on address: ', beaconAddress)); + + const attachTo = new zk.ContractFactory( + boxV2Artifact.abi, + boxV2Artifact.bytecode, + deployer.zkWallet, + ); + const upgradedBox = attachTo.attach(await boxBeaconProxy.getAddress()); + + upgradedBox.connect(zkWallet); + // wait some time before the next call + await new Promise((resolve) => setTimeout(resolve, 2000)); + const value = await upgradedBox.retrieve(); + console.info(chalk.cyan('New box value is', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example/scripts/upgrade-box-beacon.ts b/examples/upgradable-example/scripts/upgrade-box-beacon.ts index 7f9832430..33b5a2519 100644 --- a/examples/upgradable-example/scripts/upgrade-box-beacon.ts +++ b/examples/upgradable-example/scripts/upgrade-box-beacon.ts @@ -14,25 +14,25 @@ async function main() { const contractName = 'Box'; const contract = await deployer.loadArtifact(contractName); - const beacon = await hre.zkUpgrades.deployBeacon(deployer.zkWallet, contract); + const beacon = await hre.upgrades.deployBeacon(deployer.zkWallet, contract); await beacon.waitForDeployment(); const beaconAddress = await beacon.getAddress(); - const boxBeaconProxy = await hre.zkUpgrades.deployBeaconProxy(deployer.zkWallet, beaconAddress, contract, [42]); + const boxBeaconProxy = await hre.upgrades.deployBeaconProxy(deployer.zkWallet, beaconAddress, contract, [42]); await boxBeaconProxy.waitForDeployment(); // upgrade beacon const boxV2Implementation = await deployer.loadArtifact('BoxV2'); - await hre.zkUpgrades.upgradeBeacon(deployer.zkWallet, beaconAddress, boxV2Implementation); + await hre.upgrades.upgradeBeacon(deployer.zkWallet, beaconAddress, boxV2Implementation); console.info(chalk.green('Successfully upgraded beacon Box to BoxV2 on address: ', beaconAddress)); const attachTo = new zk.ContractFactory( boxV2Implementation.abi, boxV2Implementation.bytecode, deployer.zkWallet, - deployer.deploymentType, + 'create', ); const upgradedBox = attachTo.attach(await boxBeaconProxy.getAddress()); diff --git a/examples/upgradable-example/scripts/upgrade-box-factory.ts b/examples/upgradable-example/scripts/upgrade-box-factory.ts new file mode 100644 index 000000000..3b7d68a1e --- /dev/null +++ b/examples/upgradable-example/scripts/upgrade-box-factory.ts @@ -0,0 +1,35 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import chalk from 'chalk'; + +import * as hre from 'hardhat'; + +async function main() { + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + const deployer = new Deployer(hre, zkWallet); + // deploy proxy + const contractName = 'Box'; + + const boxFactory = await hre.zksyncEthers.getContractFactory(contractName, deployer.zkWallet); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'store' }); + + await box.waitForDeployment(); + + // upgrade proxy implementation + + const boxV2Factory = await hre.zksyncEthers.getContractFactory('BoxV2',deployer.zkWallet); + const upgradedBox = await hre.upgrades.upgradeProxy(await box.getAddress(), boxV2Factory); + console.info(chalk.green('Successfully upgraded Box to BoxV2')); + + upgradedBox.connect(zkWallet); + // wait some time before the next call + await new Promise((resolve) => setTimeout(resolve, 2000)); + const value = await upgradedBox.retrieve(); + console.info(chalk.cyan('Box value is', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/examples/upgradable-example/scripts/upgrade-box-uups.ts b/examples/upgradable-example/scripts/upgrade-box-uups.ts index 25abcee52..c259ace14 100644 --- a/examples/upgradable-example/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example/scripts/upgrade-box-uups.ts @@ -13,14 +13,14 @@ async function main() { const contractName = 'BoxUups'; const contract = await deployer.loadArtifact(contractName); - const box = await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); await box.waitForDeployment(); // upgrade proxy implementation const BoxUupsV2 = await deployer.loadArtifact('BoxUupsV2'); - const upgradedBox = await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, await box.getAddress(), BoxUupsV2); + const upgradedBox = await hre.upgrades.upgradeProxy(deployer.zkWallet, await box.getAddress(), BoxUupsV2); console.info(chalk.green('Successfully upgraded BoxUups to BoxUupsV2')); upgradedBox.connect(zkWallet); diff --git a/examples/upgradable-example/scripts/upgrade-box.ts b/examples/upgradable-example/scripts/upgrade-box.ts index 8c456d6bd..21daff61b 100644 --- a/examples/upgradable-example/scripts/upgrade-box.ts +++ b/examples/upgradable-example/scripts/upgrade-box.ts @@ -12,14 +12,13 @@ async function main() { const contractName = 'Box'; const contract = await deployer.loadArtifact(contractName); - const box = await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'store' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'store' }); await box.waitForDeployment(); // upgrade proxy implementation - const BoxV2 = await deployer.loadArtifact('BoxV2'); - const upgradedBox = await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, await box.getAddress(), BoxV2); + const upgradedBox = await hre.upgrades.upgradeProxy(deployer.zkWallet, await box.getAddress(), BoxV2); console.info(chalk.green('Successfully upgraded Box to BoxV2')); upgradedBox.connect(zkWallet); diff --git a/packages/hardhat-zksync-upgradable/package.json b/packages/hardhat-zksync-upgradable/package.json index b5aebed14..77993338c 100644 --- a/packages/hardhat-zksync-upgradable/package.json +++ b/packages/hardhat-zksync-upgradable/package.json @@ -35,18 +35,19 @@ "dependencies": { "@matterlabs/hardhat-zksync-deploy": "workspace:^", "@matterlabs/hardhat-zksync-solc": "workspace:^", - "@openzeppelin/upgrades-core": "^1.31.3", "@openzeppelin/contracts-hardhat-zksync-upgradable": "npm:@openzeppelin/contracts@^4.9.2", + "@openzeppelin/hardhat-upgrades": "^3.2.1", + "@openzeppelin/upgrades-core": "^1.31.3", "chalk": "^4.1.2", - "hardhat": "^2.22.5", - "fs-extra": "^11.2.0", + "compare-versions": "^6.1.0", "ethereumjs-util": "^7.1.5", "ethers": "^6.12.2", - "zksync-ethers": "^6.8.0", - "solidity-ast": "^0.4.56", + "fs-extra": "^11.2.0", + "hardhat": "^2.22.5", "proper-lockfile": "^4.1.2", "semver": "^7.6.2", - "compare-versions": "^6.1.0" + "solidity-ast": "^0.4.56", + "zksync-ethers": "^6.8.0" }, "devDependencies": { "@types/fs-extra": "^11.0.4", @@ -54,6 +55,7 @@ "@types/proper-lockfile": "^4.1.2", "@typescript-eslint/eslint-plugin": "^7.12.0", "@typescript-eslint/parser": "^7.12.0", + "c8": "^8.0.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", @@ -63,10 +65,8 @@ "prettier": "^3.3.0", "rimraf": "^5.0.7", "ts-node": "^10.9.2", - "typescript": "^5.3.0", - "c8": "^8.0.1" + "typescript": "^5.3.0" }, - "peerDependencies": {}, "prettier": { "tabWidth": 4, "printWidth": 120, diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index 276962c9d..d62222029 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -9,7 +9,8 @@ import { } from 'hardhat/builtin-tasks/task-names'; import { lazyObject } from 'hardhat/plugins'; -import { HardhatUpgrades, RunCompilerArgs } from './interfaces'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { HardhatUpgrades, HardhatZksyncUpgrades, RunCompilerArgs } from './interfaces'; import { extendCompilerOutputSelection, isFullZkSolcOutput } from './utils/utils-general'; import { validate } from './core/validate'; import { @@ -20,46 +21,174 @@ import { } from './task-names'; import { deployZkSyncBeacon, deployZkSyncProxy, upgradeZkSyncBeacon, upgradeZkSyncProxy } from './task-actions'; import { checkOpenzeppelinVersions, getUpgradableContracts } from './utils'; +import { silenceWarnings } from './log'; extendEnvironment((hre) => { - hre.zkUpgrades = lazyObject((): HardhatUpgrades => { - const { makeDeployProxy } = require('./proxy-deployment/deploy-proxy'); - const { makeUpgradeProxy } = require('./proxy-upgrade/upgrade-proxy'); - const { makeValidateImplementation } = require('./validations/validate-implementation'); - const { makeDeployBeacon } = require('./proxy-deployment/deploy-beacon'); - const { makeDeployBeaconProxy } = require('./proxy-deployment/deploy-beacon-proxy'); - const { makeUpgradeBeacon } = require('./proxy-upgrade/upgrade-beacon'); - const { makeDeployProxyAdmin } = require('./proxy-deployment/deploy-proxy-admin'); - const { makeEstimateGasProxy } = require('./gas-estimation/estimate-gas-proxy'); - const { makeEstimateGasBeacon } = require('./gas-estimation/estimate-gas-beacon'); - const { makeEstimateGasBeaconProxy } = require('./gas-estimation/estimate-gas-beacon-proxy'); - const { makeGetInstanceFunction, makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); - return { - deployProxy: checkOpenzeppelinVersions(makeDeployProxy(hre)), - upgradeProxy: checkOpenzeppelinVersions(makeUpgradeProxy(hre)), - validateImplementation: checkOpenzeppelinVersions(makeValidateImplementation(hre)), - deployBeacon: checkOpenzeppelinVersions(makeDeployBeacon(hre)), - deployBeaconProxy: checkOpenzeppelinVersions(makeDeployBeaconProxy(hre)), - upgradeBeacon: checkOpenzeppelinVersions(makeUpgradeBeacon(hre)), - deployProxyAdmin: checkOpenzeppelinVersions(makeDeployProxyAdmin(hre)), - admin: { - getInstance: checkOpenzeppelinVersions(makeGetInstanceFunction(hre)), - changeProxyAdmin: checkOpenzeppelinVersions(makeChangeProxyAdmin(hre)), - transferProxyAdminOwnership: checkOpenzeppelinVersions(makeTransferProxyAdminOwnership(hre)), - }, - estimation: { - estimateGasProxy: checkOpenzeppelinVersions(makeEstimateGasProxy(hre)), - estimateGasBeacon: checkOpenzeppelinVersions(makeEstimateGasBeacon(hre)), - estimateGasBeaconProxy: checkOpenzeppelinVersions(makeEstimateGasBeaconProxy(hre)), - }, - }; - }); - - hre.config.solidity.compilers.forEach((compiler) => { - extendCompilerOutputSelection(compiler); - }); + if (hre.network.zksync) { + hre.zkUpgrades = lazyObject(() => { + return makeZkSyncFunction(hre) as HardhatZksyncUpgrades & HardhatUpgrades; + }); + + hre.upgrades = lazyObject(() => { + return makeZkSyncFunction(hre) as HardhatZksyncUpgrades & HardhatUpgrades; + }); + + hre.defender = undefined; + + hre.config.solidity.compilers.forEach((compiler) => { + extendCompilerOutputSelection(compiler); + }); + } else { + hre.upgrades = lazyObject(() => { + return makeUpgradesFunctions(hre) as HardhatZksyncUpgrades & HardhatUpgrades; + }); + + warnOnHardhatDefender(); + + hre.defender = lazyObject(() => { + return makeDefenderFunctions(hre); + }); + + hre.zkUpgrades = undefined as any; + } }); +function warnOnHardhatDefender() { + if (tryRequire('@openzeppelin/hardhat-defender', true)) { + const { logWarning } = require('@openzeppelin/upgrades-core'); + logWarning('The @openzeppelin/hardhat-defender package is deprecated.', [ + 'Uninstall the @openzeppelin/hardhat-defender package.', + 'OpenZeppelin Defender integration is included as part of the Hardhat Upgrades plugin.', + ]); + } +} + +function tryRequire(id: string, resolveOnly?: boolean) { + try { + if (resolveOnly) { + require.resolve(id); + } else { + require(id); + } + return true; + } catch (e: any) { + // do nothing + } + return false; +} + +function makeFunctions(hre: HardhatRuntimeEnvironment, defender: boolean): HardhatUpgrades { + const { getImplementationAddressFromBeacon } = require('@openzeppelin/upgrades-core/dist/impl-address'); + const { + getAdminAddress, + getImplementationAddress, + getBeaconAddress, + } = require('@openzeppelin/upgrades-core/dist/eip-1967'); + const { makeDeployProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy'); + const { makeUpgradeProxy } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'); + const { makeValidateImplementation } = require('@openzeppelin/hardhat-upgrades/dist/validate-implementation'); + const { makeValidateUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/validate-upgrade'); + const { makeDeployImplementation } = require('@openzeppelin/hardhat-upgrades/dist/deploy-implementation'); + const { makePrepareUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'); + const { makeDeployBeacon } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon'); + const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); + const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); + const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); + /* eslint-disable @typescript-eslint/no-shadow */ + const { + makeChangeProxyAdmin, + makeTransferProxyAdminOwnership, + } = require('@openzeppelin/hardhat-upgrades/dist/admin'); + /* eslint-enable @typescript-eslint/no-shadow */ + + return { + silenceWarnings, + deployProxy: makeDeployProxy(hre, defender), + upgradeProxy: makeUpgradeProxy(hre, defender), // block on defender + validateImplementation: makeValidateImplementation(hre), + validateUpgrade: makeValidateUpgrade(hre), + deployImplementation: makeDeployImplementation(hre, defender), + prepareUpgrade: makePrepareUpgrade(hre, defender), + deployBeacon: makeDeployBeacon(hre, defender), // block on defender + deployBeaconProxy: makeDeployBeaconProxy(hre, defender), + upgradeBeacon: makeUpgradeBeacon(hre, defender), // block on defender + forceImport: makeForceImport(hre), + admin: { + changeProxyAdmin: makeChangeProxyAdmin(hre, defender), // block on defender + transferProxyAdminOwnership: makeTransferProxyAdminOwnership(hre, defender), // block on defender + }, + erc1967: { + getAdminAddress: (proxyAddress: string) => getAdminAddress(hre.network.provider, proxyAddress), + getImplementationAddress: (proxyAddress: string) => + getImplementationAddress(hre.network.provider, proxyAddress), + getBeaconAddress: (proxyAddress: string) => getBeaconAddress(hre.network.provider, proxyAddress), + }, + beacon: { + getImplementationAddress: (beaconAddress: string) => + getImplementationAddressFromBeacon(hre.network.provider, beaconAddress), + }, + }; +} + +function makeDefenderFunctions(hre: HardhatRuntimeEnvironment) { + const { makeDeployContract } = require('@openzeppelin/hardhat-upgrades/dist/deploy-contract'); + const { + makeProposeUpgradeWithApproval, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'); + const { + makeGetDeployApprovalProcess, + makeGetUpgradeApprovalProcess, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'); + + const getUpgradeApprovalProcess = makeGetUpgradeApprovalProcess(hre); + + return { + ...makeFunctions(hre, true), + deployContract: makeDeployContract(hre, true), + proposeUpgradeWithApproval: makeProposeUpgradeWithApproval(hre, true), + getDeployApprovalProcess: makeGetDeployApprovalProcess(hre), + getUpgradeApprovalProcess, + getDefaultApprovalProcess: getUpgradeApprovalProcess, // deprecated, is an alias for getUpgradeApprovalProcess + }; +} + +function makeUpgradesFunctions(hre: HardhatRuntimeEnvironment): HardhatUpgrades { + return makeFunctions(hre, false); +} + +function makeZkSyncFunction(hre: HardhatRuntimeEnvironment): HardhatZksyncUpgrades { + const { makeDeployProxy } = require('./proxy-deployment/deploy-proxy'); + const { makeUpgradeProxy } = require('./proxy-upgrade/upgrade-proxy'); + const { makeValidateImplementation } = require('./validations/validate-implementation'); + const { makeDeployBeacon } = require('./proxy-deployment/deploy-beacon'); + const { makeDeployBeaconProxy } = require('./proxy-deployment/deploy-beacon-proxy'); + const { makeUpgradeBeacon } = require('./proxy-upgrade/upgrade-beacon'); + const { makeDeployProxyAdmin } = require('./proxy-deployment/deploy-proxy-admin'); + const { makeEstimateGasProxy } = require('./gas-estimation/estimate-gas-proxy'); + const { makeEstimateGasBeacon } = require('./gas-estimation/estimate-gas-beacon'); + const { makeEstimateGasBeaconProxy } = require('./gas-estimation/estimate-gas-beacon-proxy'); + const { makeGetInstanceFunction, makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); + return { + deployProxy: checkOpenzeppelinVersions(makeDeployProxy(hre)), + upgradeProxy: checkOpenzeppelinVersions(makeUpgradeProxy(hre)), + validateImplementation: checkOpenzeppelinVersions(makeValidateImplementation(hre)), + deployBeacon: checkOpenzeppelinVersions(makeDeployBeacon(hre)), + deployBeaconProxy: checkOpenzeppelinVersions(makeDeployBeaconProxy(hre)), + upgradeBeacon: checkOpenzeppelinVersions(makeUpgradeBeacon(hre)), + deployProxyAdmin: checkOpenzeppelinVersions(makeDeployProxyAdmin(hre)), + admin: { + getInstance: checkOpenzeppelinVersions(makeGetInstanceFunction(hre)), + changeProxyAdmin: checkOpenzeppelinVersions(makeChangeProxyAdmin(hre)), + transferProxyAdminOwnership: checkOpenzeppelinVersions(makeTransferProxyAdminOwnership(hre)), + }, + estimation: { + estimateGasProxy: checkOpenzeppelinVersions(makeEstimateGasProxy(hre)), + estimateGasBeacon: checkOpenzeppelinVersions(makeEstimateGasBeacon(hre)), + estimateGasBeaconProxy: checkOpenzeppelinVersions(makeEstimateGasBeaconProxy(hre)), + }, + }; +} + task(TASK_DEPLOY_ZKSYNC_BEACON, 'Runs the beaccon deploy for ZKsync network') .addParam('contractName', 'A contract name or a FQN', '') .addOptionalVariadicPositionalParam( diff --git a/packages/hardhat-zksync-upgradable/src/interfaces.ts b/packages/hardhat-zksync-upgradable/src/interfaces.ts index e1cc0b4c5..bf1cfe2af 100644 --- a/packages/hardhat-zksync-upgradable/src/interfaces.ts +++ b/packages/hardhat-zksync-upgradable/src/interfaces.ts @@ -2,29 +2,87 @@ import { SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; import * as zk from 'zksync-ethers'; -import { DeployAdminFunction } from './proxy-deployment/deploy-proxy-admin'; -import { UpgradeFunction } from './proxy-upgrade/upgrade-proxy'; -import { DeployBeaconFunction } from './proxy-deployment/deploy-beacon'; -import { DeployBeaconProxyFunction } from './proxy-deployment/deploy-beacon-proxy'; -import { UpgradeBeaconFunction } from './proxy-upgrade/upgrade-beacon'; -import { DeployFunction } from './proxy-deployment/deploy-proxy'; -import { ValidateImplementationOptions } from './utils/options'; -import { ChangeAdminFunction, GetInstanceFunction, TransferProxyAdminOwnershipFunction } from './admin'; -import { EstimateBeaconGasFunction } from './gas-estimation/estimate-gas-beacon-proxy'; +import { DeployFunction as _DeployFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy'; +import { PrepareUpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'; +import { UpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'; +import { DeployBeaconFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; +import { DeployBeaconProxyFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; +import { UpgradeBeaconFunction } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; +import { ForceImportFunction } from '@openzeppelin/hardhat-upgrades/dist/force-import'; +import { + ChangeAdminFunction as _ChangeAdminFunction, + TransferProxyAdminOwnershipFunction as _TransferProxyAdminOwnershipFunction, +} from '@openzeppelin/hardhat-upgrades/dist/admin'; +import { ValidateImplementationFunction as _ValidateImplementationFunction } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; +import { ValidateUpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; +import { DeployImplementationFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-implementation'; +import { DeployContractFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-contract'; +// import { ProposeUpgradeWithApprovalFunction } from '@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'; +import { + GetDeployApprovalProcessFunction, + GetUpgradeApprovalProcessFunction, +} from '@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'; +import { UpgradeProxyArtifact, UpgradeProxyFactory } from './proxy-upgrade/upgrade-proxy'; +import { UpgradeBeaconArtifact, UpgradeBeaconFactory } from './proxy-upgrade/upgrade-beacon'; +import { DeployFunctionArtifact, DeployFunctionFactory } from './proxy-deployment/deploy-proxy'; +import { DeployBeaconArtifact, DeployBeaconFactory } from './proxy-deployment/deploy-beacon'; +import { DeployBeaconProxyArtifact, DeployBeaconProxyFactory } from './proxy-deployment/deploy-beacon-proxy'; import { EstimateProxyGasFunction } from './gas-estimation/estimate-gas-proxy'; +import { EstimateBeaconGasFunction } from './gas-estimation/estimate-gas-beacon-proxy'; +import { ChangeAdminFunction, GetInstanceFunction, TransferProxyAdminOwnershipFunction } from './admin'; +import { ValidateImplementationOptions } from './utils/options'; +import { DeployAdminFunction } from './proxy-deployment/deploy-proxy-admin'; + +export interface HardhatUpgrades { + deployProxy: _DeployFunction; + upgradeProxy: UpgradeFunction; + validateImplementation: _ValidateImplementationFunction; + validateUpgrade: ValidateUpgradeFunction; + deployImplementation: DeployImplementationFunction; + prepareUpgrade: PrepareUpgradeFunction; + deployBeacon: DeployBeaconFunction; + deployBeaconProxy: DeployBeaconProxyFunction; + upgradeBeacon: UpgradeBeaconFunction; + forceImport: ForceImportFunction; + // silenceWarnings: typeof silenceWarnings; + silenceWarnings: any; + admin: { + changeProxyAdmin: _ChangeAdminFunction; + transferProxyAdminOwnership: _TransferProxyAdminOwnershipFunction; + }; + erc1967: { + getAdminAddress: (proxyAdress: string) => Promise; + getImplementationAddress: (proxyAdress: string) => Promise; + getBeaconAddress: (proxyAdress: string) => Promise; + }; + beacon: { + getImplementationAddress: (beaconAddress: string) => Promise; + }; +} + +export type DefenderHardhatUpgrades = { + deployContract: DeployContractFunction; + proposeUpgradeWithApproval: any; + getDeployApprovalProcess: GetDeployApprovalProcessFunction; + getUpgradeApprovalProcess: GetUpgradeApprovalProcessFunction; + /** + * @deprecated Use `getUpgradeApprovalProcess` instead. + */ + getDefaultApprovalProcess: GetUpgradeApprovalProcessFunction; +} & HardhatUpgrades; export type ValidateImplementationFunction = ( ImplFactory: zk.ContractFactory, opts?: ValidateImplementationOptions, ) => Promise; -export interface HardhatUpgrades { - deployProxy: DeployFunction; - upgradeProxy: UpgradeFunction; +export interface HardhatZksyncUpgrades { + deployProxy: DeployFunctionArtifact & DeployFunctionFactory; + upgradeProxy: UpgradeProxyFactory & UpgradeProxyArtifact; validateImplementation: ValidateImplementationFunction; - deployBeacon: DeployBeaconFunction; - deployBeaconProxy: DeployBeaconProxyFunction; - upgradeBeacon: UpgradeBeaconFunction; + deployBeacon: DeployBeaconArtifact & DeployBeaconFactory; + deployBeaconProxy: DeployBeaconProxyFactory & DeployBeaconProxyArtifact; + upgradeBeacon: UpgradeBeaconFactory & UpgradeBeaconArtifact; deployProxyAdmin: DeployAdminFunction; admin: { getInstance: GetInstanceFunction; diff --git a/packages/hardhat-zksync-upgradable/src/log.ts b/packages/hardhat-zksync-upgradable/src/log.ts new file mode 100644 index 000000000..0fdefdf14 --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/log.ts @@ -0,0 +1,32 @@ +import chalk from 'chalk'; + +function logWarning(title: string, lines: string[] = []): void { + log('Warning', title, lines); +} + +function indent(text: string, amount: number, amount0 = amount): string { + return text.replace(/^/gm, (_, i) => ' '.repeat(i === 0 ? amount0 : amount)); +} + +let silenced = false; + +function log(prefix: string, title: string, lines: string[]): void { + if (silenced) { + return; + } + + const parts = [`${chalk.yellow.bold(`${prefix}:`)} ${title}\n`]; + + if (lines.length > 0) { + parts.push(lines.map((l) => `${indent(l, 4)}\n`).join('')); + } + + console.error(parts.join('\n')); +} + +export function silenceWarnings(): void { + logWarning(`All subsequent Upgrades warnings will be silenced.`, [ + `Make sure you have manually checked all uses of unsafe flags.`, + ]); + silenced = true; +} diff --git a/packages/hardhat-zksync-upgradable/src/plugin.ts b/packages/hardhat-zksync-upgradable/src/plugin.ts index 9228e6d6f..fb0ff54ce 100644 --- a/packages/hardhat-zksync-upgradable/src/plugin.ts +++ b/packages/hardhat-zksync-upgradable/src/plugin.ts @@ -2,7 +2,7 @@ import { Deployer } from '@matterlabs/hardhat-zksync-deploy/dist/deployer'; import { getConstructorArguments } from '@matterlabs/hardhat-zksync-deploy/dist/utils'; import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { Contract } from 'zksync-ethers'; +import { Contract, ContractFactory } from 'zksync-ethers'; import { DeploymentType } from 'zksync-ethers/build/types'; import { getWallet } from './utils'; @@ -36,13 +36,14 @@ export async function deployBeacon( const deployer = new Deployer(hre, wallet); const contract = await deployer.loadArtifact(taskArgs.contractName); - const beacon = await hre.zkUpgrades.deployBeacon(wallet, contract, { + const factory = new ContractFactory(contract.abi, contract.bytecode, wallet); + const beacon = await hre.upgrades.deployBeacon(factory, [], { deploymentType: taskArgs.deploymentTypeImpl, salt: taskArgs.saltImpl, }); await beacon.waitForDeployment(); - const proxy = await hre.zkUpgrades.deployBeaconProxy( + const proxy = await hre.upgrades.deployBeaconProxy( deployer.zkWallet, await beacon.getAddress(), contract, @@ -89,7 +90,7 @@ export async function deployProxy( const contract = await deployer.loadArtifact(taskArgs.contractName); - const proxy = await hre.zkUpgrades.deployProxy(wallet, contract, constructorArguments, { + const proxy = await hre.upgrades.deployProxy(wallet, contract, constructorArguments, { deploymentTypeImpl: taskArgs.deploymentTypeImpl, saltImpl: taskArgs.saltImpl, deploymentTypeProxy: taskArgs.deploymentTypeProxy, @@ -121,7 +122,7 @@ export async function upgradeBeacon( const contractV2 = await deployer.loadArtifact(taskArgs.contractName); - const beaconUpgrade = await hre.zkUpgrades.upgradeBeacon(wallet, taskArgs.beaconAddress, contractV2, { + const beaconUpgrade = await hre.upgrades.upgradeBeacon(wallet, taskArgs.beaconAddress, contractV2, { deploymentType: taskArgs.deploymentType, salt: taskArgs.salt, }); @@ -150,7 +151,7 @@ export async function upgradeProxy( const contractV2 = await deployer.loadArtifact(taskArgs.contractName); - const proxyUpgrade = await hre.zkUpgrades.upgradeProxy(wallet, taskArgs.proxyAddress, contractV2, { + const proxyUpgrade = await hre.upgrades.upgradeProxy(wallet, taskArgs.proxyAddress, contractV2, { deploymentType: taskArgs.deploymentType, salt: taskArgs.salt, }); diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts index 2192c3b24..a47577df2 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts @@ -16,106 +16,143 @@ import path from 'path'; import { ContractAddressOrInstance, getContractAddress, getInitializerData } from '../utils/utils-general'; import { DeployBeaconProxyOptions } from '../utils/options'; import { BEACON_PROXY_JSON } from '../constants'; -import { ZkSyncUpgradablePluginError } from '../errors'; import { Manifest } from '../core/manifest'; import { getUpgradableContracts } from '../utils'; import { deploy, DeployTransaction } from './deploy'; -export interface DeployBeaconProxyFunction { - ( - wallet: zk.Wallet, - beacon: ContractAddressOrInstance, - artifact: ZkSyncArtifact, - args?: unknown[], - opts?: DeployBeaconProxyOptions, - quiet?: boolean, - ): Promise; - ( - wallet: zk.Wallet, - beacon: ContractAddressOrInstance, - artifact: ZkSyncArtifact, - opts?: DeployBeaconProxyOptions, - ): Promise; -} - -export function makeDeployBeaconProxy(hre: HardhatRuntimeEnvironment): DeployBeaconProxyFunction { - return async function deployBeaconProxy( - wallet: zk.Wallet, - beacon: ContractAddressOrInstance, - artifact: ZkSyncArtifact, - args: unknown[] | DeployBeaconProxyOptions = [], - opts: DeployBeaconProxyOptions = {}, - quiet: boolean = false, - ) { - const attachTo = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); - - if (!(attachTo instanceof zk.ContractFactory)) { - throw new ZkSyncUpgradablePluginError( - `attachTo must specify a contract factory\n` + - `Include the contract factory for the beacon's current implementation in the attachTo parameter`, - ); - } - if (!Array.isArray(args)) { - opts = args; - args = []; - } - - const manifest = await Manifest.forNetwork(wallet.provider); - - if (opts.kind !== undefined && opts.kind !== 'beacon') { - throw new DeployBeaconProxyKindError(opts.kind); - } - opts.kind = 'beacon'; - - const beaconAddress = await getContractAddress(beacon); - if (!(await isBeacon(wallet.provider, beaconAddress))) { - throw new DeployBeaconProxyUnsupportedError(beaconAddress); +export type DeployBeaconProxyFactory = ( + beacon: ContractAddressOrInstance, + factory: zk.ContractFactory, + args?: unknown[], + opts?: DeployBeaconProxyOptions, + quiet?: boolean, +) => Promise; + +export type DeployBeaconProxyArtifact = ( + wallet: zk.Wallet, + beacon: ContractAddressOrInstance, + artifact: ZkSyncArtifact, + args?: unknown[], + opts?: DeployBeaconProxyOptions, + quiet?: boolean, +) => Promise; + +export function makeDeployBeaconProxy( + hre: HardhatRuntimeEnvironment, +): DeployBeaconProxyFactory | DeployBeaconProxyArtifact { + return async function ( + ...args: Parameters + ): Promise { + const target = args[0]; + if (target instanceof zk.ContractFactory) { + return deployBeaconProxyFactory(hre, ...(args as Parameters)); + } else { + return deployBeaconProxyArtifact(hre, ...(args as Parameters)); } + }; +} - const data = getInitializerData(attachTo.interface, args, opts.initializer); - - if (await manifest.getAdmin()) { - if (!quiet) { - console.info( - chalk.yellow(`A proxy admin was previously deployed on this network`, [ - `This is not natively used with the current kind of proxy ('beacon').`, - `Changes to the admin will have no effect on this new proxy.`, - ]), - ); - } - } +export function deployBeaconProxyArtifact( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + beacon: ContractAddressOrInstance, + artifact: ZkSyncArtifact, + args: unknown[] = [], + opts: DeployBeaconProxyOptions = {}, + quiet: boolean = false, +): Promise { + if (opts && opts.kind !== undefined && opts.kind !== 'beacon') { + throw new DeployBeaconProxyKindError(opts.kind); + } + const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); + opts = opts || {}; + opts.kind = 'beacon'; + return deployBeaconProxy(hre, beacon, factory, args, opts, wallet, quiet); +} - const beaconProxyPath = (await hre.artifacts.getArtifactPaths()).find((artifactPath) => - artifactPath.includes(path.sep + getUpgradableContracts().BeaconProxy + path.sep + BEACON_PROXY_JSON), - ); - assert(beaconProxyPath, 'Beacon proxy artifact not found'); - const beaconProxyContract = await import(beaconProxyPath); - - const beaconProxyFactory = new zk.ContractFactory( - beaconProxyContract.abi, - beaconProxyContract.bytecode, - wallet, - opts.deploymentType, - ); - - const proxyDeployment: Required = { - kind: opts.kind, - ...(await deploy(beaconProxyFactory, beaconAddress, data, { - customData: { - salt: opts.salt, - }, - })), - }; +export async function deployBeaconProxyFactory( + hre: HardhatRuntimeEnvironment, + beacon: ContractAddressOrInstance, + factory: zk.ContractFactory, + args: unknown[] = [], + opts: DeployBeaconProxyOptions = {}, + quiet: boolean = false, +): Promise { + if (opts && opts.kind !== undefined && opts.kind !== 'beacon') { + throw new DeployBeaconProxyKindError(opts.kind); + } + opts = opts || {}; + opts.kind = 'beacon'; + + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) throw new Error('Wallet not found. Please pass it in the arguments.'); + + return deployBeaconProxy(hre, beacon, factory, args, opts, wallet, quiet); +} +async function deployBeaconProxy( + hre: HardhatRuntimeEnvironment, + beacon: ContractAddressOrInstance, + attachTo: zk.ContractFactory, + args: unknown[] = [], + opts: DeployBeaconProxyOptions = {}, + wallet: zk.Wallet, + quiet: boolean = false, +): Promise { + if (!Array.isArray(args)) { + opts = args; + args = []; + } + + const manifest = await Manifest.forNetwork(wallet.provider); + const beaconAddress = await getContractAddress(beacon); + if (!(await isBeacon(wallet.provider, beaconAddress))) { + throw new DeployBeaconProxyUnsupportedError(beaconAddress); + } + + const data = getInitializerData(attachTo.interface, args, opts.initializer); + + if (await manifest.getAdmin()) { if (!quiet) { - console.info(chalk.green('Beacon proxy deployed at: ', proxyDeployment.address)); + console.info( + chalk.yellow(`A proxy admin was previously deployed on this network`, [ + `This is not natively used with the current kind of proxy ('beacon').`, + `Changes to the admin will have no effect on this new proxy.`, + ]), + ); } + } + + const beaconProxyPath = (await hre.artifacts.getArtifactPaths()).find((artifactPath) => + artifactPath.includes(path.sep + getUpgradableContracts().BeaconProxy + path.sep + BEACON_PROXY_JSON), + ); + assert(beaconProxyPath, 'Beacon proxy artifact not found'); + const beaconProxyContract = await import(beaconProxyPath); + + const beaconProxyFactory = new zk.ContractFactory( + beaconProxyContract.abi, + beaconProxyContract.bytecode, + wallet, + opts.deploymentType, + ); + + const proxyDeployment: Required = { + kind: opts.kind!, + ...(await deploy(beaconProxyFactory, beaconAddress, data, { + customData: { + salt: opts.salt, + }, + })), + }; - await manifest.addProxy(proxyDeployment); + if (!quiet) { + console.info(chalk.green('Beacon proxy deployed at: ', proxyDeployment.address)); + } - const inst = attachTo.attach(proxyDeployment.address); - // @ts-ignore Won't be readonly because inst was created through attach. - inst.deployTransaction = proxyDeployment.deployTransaction; - return inst; - }; + await manifest.addProxy(proxyDeployment); + + const inst = attachTo.attach(proxyDeployment.address) as zk.Contract; + // @ts-ignore Won't be readonly because inst was created through attach. + inst.deployTransaction = proxyDeployment.deployTransaction; + return inst.runner ? inst : (inst.connect(wallet) as zk.Contract); } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts index c3c23238a..f01bab07d 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts @@ -9,55 +9,114 @@ import chalk from 'chalk'; import assert from 'assert'; import path from 'path'; import { UPGRADABLE_BEACON_JSON } from '../constants'; +import { extractFactoryDeps, getArtifactFromBytecode } from '../utils/utils-general'; +import { ZkSyncUpgradablePluginError } from '../errors'; import { DeployBeaconOptions } from '../utils/options'; -import { extractFactoryDeps } from '../utils/utils-general'; import { getUpgradableContracts } from '../utils'; import { deployBeaconImpl } from './deploy-impl'; import { deploy, DeployTransaction } from './deploy'; -export type DeployBeaconFunction = ( +export type DeployBeaconFactory = ( + factory: zk.ContractFactory, + args?: unknown[], + opts?: DeployBeaconOptions, + quiet?: boolean, +) => Promise; + +export type DeployBeaconArtifact = ( wallet: zk.Wallet, artifact: ZkSyncArtifact, + args?: unknown[], opts?: DeployBeaconOptions, quiet?: boolean, ) => Promise; -export function makeDeployBeacon(hre: HardhatRuntimeEnvironment): DeployBeaconFunction { - return async function deployBeacon( - wallet: zk.Wallet, - artifact: ZkSyncArtifact, - opts: DeployBeaconOptions = {}, - quiet: boolean = false, - ): Promise { - const beaconImplFactory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet, opts.deploymentType); - - opts.provider = wallet.provider; - opts.factoryDeps = await extractFactoryDeps(hre, artifact); - - const { impl } = await deployBeaconImpl(hre, beaconImplFactory, opts); - if (!quiet) { - console.info(chalk.green('Beacon impl deployed at', impl)); +export function makeDeployBeacon(hre: HardhatRuntimeEnvironment): DeployBeaconFactory | DeployBeaconArtifact { + return async function (...args: Parameters): Promise { + const target = args[0]; + if (target instanceof zk.ContractFactory) { + return await deployBeaconFactory(hre, ...(args as Parameters)); + } else { + return deployBeaconArtifact(hre, ...(args as Parameters)); } + }; +} - const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), - ); - assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); - const upgradeableBeaconContract = await import(upgradableBeaconPath); - - const upgradeableBeaconFactory = new zk.ContractFactory( - upgradeableBeaconContract.abi, - upgradeableBeaconContract.bytecode, - wallet, - ); - const beaconDeployment: Required = await deploy(upgradeableBeaconFactory, impl); - if (!quiet) { - console.info(chalk.green('Beacon deployed at: ', beaconDeployment.address)); - } +export async function deployBeaconFactory( + hre: HardhatRuntimeEnvironment, + factory: zk.ContractFactory, + args?: unknown[], + opts?: DeployBeaconOptions, + quiet?: boolean, +): Promise { + if (!Array.isArray(args)) { + opts = args; + args = []; + } - const beaconContract = upgradeableBeaconFactory.attach(beaconDeployment.address); - // @ts-ignore Won't be readonly because beaconContract was created through attach. - beaconContract.deployTransaction = beaconDeployment.deployTransaction; - return beaconContract; - }; + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) { + throw new ZkSyncUpgradablePluginError('Wallet is required for deployment'); + } + + opts = opts || {}; + opts.provider = wallet?.provider; + opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); + + return deployProxyBeacon(hre, factory, wallet, args, opts, quiet); +} + +export async function deployBeaconArtifact( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + artifact: ZkSyncArtifact, + args?: unknown[], + opts?: DeployBeaconOptions, + quiet?: boolean, +): Promise { + const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, artifact as ZkSyncArtifact); + return deployProxyBeacon(hre, factory, wallet, args, opts, quiet); +} + +async function deployProxyBeacon( + hre: HardhatRuntimeEnvironment, + factory: zk.ContractFactory, + wallet: zk.Wallet, + args: unknown[] | DeployBeaconOptions = [], + opts: DeployBeaconOptions = {}, + quiet: boolean = false, +): Promise { + if (!Array.isArray(args)) { + opts = args; + args = []; + } + + const { impl } = await deployBeaconImpl(hre, factory, opts); + if (!quiet) { + console.info(chalk.green('Beacon impl deployed at', impl)); + } + + const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), + ); + assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); + const upgradeableBeaconContract = await import(upgradableBeaconPath); + + const upgradeableBeaconFactory = new zk.ContractFactory( + upgradeableBeaconContract.abi, + upgradeableBeaconContract.bytecode, + wallet, + ); + const beaconDeployment: Required = await deploy(upgradeableBeaconFactory, impl); + if (!quiet) { + console.info(chalk.green('Beacon deployed at: ', beaconDeployment.address)); + } + + const beaconContract = upgradeableBeaconFactory.attach(beaconDeployment.address); + // @ts-ignore Won't be readonly because beaconContract was created through attach. + beaconContract.deployTransaction = beaconDeployment.deployTransaction; + return beaconContract.runner ? beaconContract : (beaconContract.connect(wallet) as zk.Contract); } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts index f415b1522..5fc094369 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts @@ -7,16 +7,23 @@ import { BeaconProxyUnsupportedError } from '@openzeppelin/upgrades-core'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import assert from 'assert'; -import { extractFactoryDeps, getInitializerData } from '../utils/utils-general'; -import { TUP_JSON, ERC1967_PROXY_JSON } from '../constants'; +import { extractFactoryDeps, getArtifactFromBytecode, getInitializerData } from '../utils/utils-general'; +import { ERC1967_PROXY_JSON, TUP_JSON } from '../constants'; import { Manifest, ProxyDeployment } from '../core/manifest'; -import { DeployProxyOptions } from '../utils/options'; import { ZkSyncUpgradablePluginError } from '../errors'; +import { DeployProxyOptions } from '../utils/options'; import { getUpgradableContracts } from '../utils'; import { deployProxyImpl } from './deploy-impl'; import { DeployTransaction, deploy } from './deploy'; -export type DeployFunction = ( +export type DeployFunctionFactory = ( + factory: zk.ContractFactory, + args?: unknown[], + opts?: DeployProxyOptions, + quiet?: boolean, +) => Promise; + +export type DeployFunctionArtifact = ( wallet: zk.Wallet, artifact: ZkSyncArtifact, args?: unknown[], @@ -24,117 +31,156 @@ export type DeployFunction = ( quiet?: boolean, ) => Promise; -export function makeDeployProxy(hre: HardhatRuntimeEnvironment): DeployFunction { - return async function deployProxy( - wallet, - artifact, - args: unknown[] | DeployProxyOptions = [], - opts: DeployProxyOptions = {}, - quiet: boolean = false, - ): Promise { - if (!Array.isArray(args)) { - opts = args; - args = []; +export function makeDeployProxy(hre: HardhatRuntimeEnvironment): DeployFunctionFactory | DeployFunctionArtifact { + return async function (...args: Parameters): Promise { + const target = args[0]; + if (target instanceof zk.ContractFactory) { + return await deployProxyFactory(hre, ...(args as Parameters)); + } else { + return deployProxyArtifact(hre, ...(args as Parameters)); } - opts.provider = wallet.provider; - opts.factoryDeps = await extractFactoryDeps(hre, artifact); + }; +} + +export async function deployProxyFactory( + hre: HardhatRuntimeEnvironment, + factory: zk.ContractFactory, + args?: unknown[], + opts?: DeployProxyOptions, + quiet?: boolean, +): Promise { + if (!Array.isArray(args)) { + opts = args; + args = []; + } + + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) { + throw new ZkSyncUpgradablePluginError('Wallet is required for deployment'); + } + opts = opts || {}; + opts.provider = wallet?.provider; + opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); + + return deployProxy(hre, factory, wallet, args, opts, quiet); +} + +export async function deployProxyArtifact( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + artifact: ZkSyncArtifact, + args?: unknown[], + opts?: DeployProxyOptions, + quiet?: boolean, +): Promise { + const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, artifact as ZkSyncArtifact); + return deployProxy(hre, factory, wallet, args, opts, quiet); +} - const manifest = await Manifest.forNetwork(wallet.provider); +async function deployProxy( + hre: HardhatRuntimeEnvironment, + factory: zk.ContractFactory, + wallet: zk.Wallet, + args: unknown[] | DeployProxyOptions = [], + opts: DeployProxyOptions = {}, + quiet: boolean = false, +): Promise { + if (!Array.isArray(args)) { + opts = args; + args = []; + } + + const manifest = await Manifest.forNetwork(wallet.provider); + + const { impl, kind } = await deployProxyImpl(hre, factory, opts); + if (!quiet) { + console.info(chalk.green(`Implementation contract was deployed to ${impl}`)); + } + + const data = getInitializerData(factory.interface, args, opts.initializer); + + const customDataProxy = { + customData: { + salt: opts.saltProxy, + }, + }; - const factory = new zk.ContractFactory( - artifact.abi, - artifact.bytecode, - wallet, - opts.deploymentTypeImpl, - ); + if (kind === 'uups') { + if (await manifest.getAdmin()) { + if (!quiet) { + console.info( + chalk.yellow( + `A proxy admin was previously deployed on this network\nThis is not natively used with the current kind of proxy ('uups')\nChanges to the admin will have no effect on this new proxy`, + ), + ); + } + } + } - const { impl, kind } = await deployProxyImpl(hre, factory, opts); - if (!quiet) { - console.info(chalk.green(`Implementation contract was deployed to ${impl}`)); + let proxyDeployment: Required; + switch (kind) { + case 'beacon': { + throw new BeaconProxyUnsupportedError(); } - const data = getInitializerData(factory.interface, args, opts.initializer); - - const customDataProxy = { - customData: { - salt: opts.saltProxy, - }, - }; - - if (kind === 'uups') { - if (await manifest.getAdmin()) { - if (!quiet) { - console.info( - chalk.yellow( - `A proxy admin was previously deployed on this network\nThis is not natively used with the current kind of proxy ('uups')\nChanges to the admin will have no effect on this new proxy`, - ), - ); - } + case 'uups': { + const ERC1967ProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().ERC1967Proxy + path.sep + ERC1967_PROXY_JSON), + ); + assert(ERC1967ProxyPath, 'ERC1967Proxy artifact not found'); + const proxyContract = await import(ERC1967ProxyPath); + const proxyFactory = new zk.ContractFactory( + proxyContract.abi, + proxyContract.bytecode, + wallet, + opts.deploymentTypeProxy, + ); + proxyDeployment = { kind, ...(await deploy(proxyFactory, impl, data, customDataProxy)) }; + + if (!quiet) { + console.info(chalk.green(`UUPS proxy was deployed to ${proxyDeployment.address}`)); } + break; } - let proxyDeployment: Required; - switch (kind) { - case 'beacon': { - throw new BeaconProxyUnsupportedError(); + case 'transparent': { + const adminAddress = await hre.upgrades.deployProxyAdmin(wallet, {}); + if (!quiet) { + console.info(chalk.green(`Admin was deployed to ${adminAddress}`)); } - case 'uups': { - const ERC1967ProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ERC1967Proxy + path.sep + ERC1967_PROXY_JSON), - ); - assert(ERC1967ProxyPath, 'ERC1967Proxy artifact not found'); - const proxyContract = await import(ERC1967ProxyPath); - const proxyFactory = new zk.ContractFactory( - proxyContract.abi, - proxyContract.bytecode, - wallet, - opts.deploymentTypeProxy, - ); - proxyDeployment = { kind, ...(await deploy(proxyFactory, impl, data, customDataProxy)) }; - - if (!quiet) { - console.info(chalk.green(`UUPS proxy was deployed to ${proxyDeployment.address}`)); - } - break; + const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + TUP_JSON), + ); + assert(TUPPath, 'TUP artifact not found'); + const TUPContract = await import(TUPPath); + + const TUPFactory = new zk.ContractFactory( + TUPContract.abi, + TUPContract.bytecode, + wallet, + opts.deploymentTypeProxy, + ); + proxyDeployment = { kind, ...(await deploy(TUPFactory, impl, adminAddress, data, customDataProxy)) }; + + if (!quiet) { + console.info(chalk.green(`Transparent proxy was deployed to ${proxyDeployment.address}`)); } - case 'transparent': { - const adminAddress = await hre.zkUpgrades.deployProxyAdmin(wallet, {}); - if (!quiet) { - console.info(chalk.green(`Admin was deployed to ${adminAddress}`)); - } - - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + TUP_JSON), - ); - assert(TUPPath, 'TUP artifact not found'); - const TUPContract = await import(TUPPath); - - const TUPFactory = new zk.ContractFactory( - TUPContract.abi, - TUPContract.bytecode, - wallet, - opts.deploymentTypeProxy, - ); - proxyDeployment = { kind, ...(await deploy(TUPFactory, impl, adminAddress, data, customDataProxy)) }; - - if (!quiet) { - console.info(chalk.green(`Transparent proxy was deployed to ${proxyDeployment.address}`)); - } - - break; - } + break; + } - default: { - throw new ZkSyncUpgradablePluginError(`Unknown proxy kind: ${kind}`); - } + default: { + throw new ZkSyncUpgradablePluginError(`Unknown proxy kind: ${kind}`); } + } - await manifest.addProxy(proxyDeployment); - const inst = factory.attach(proxyDeployment.address); - // @ts-ignore Won't be readonly because inst was created through attach. - inst.deployTransaction = proxyDeployment.deployTransaction; - return inst; - }; + await manifest.addProxy(proxyDeployment); + const inst = factory.attach(proxyDeployment.address); + // @ts-ignore Won't be readonly because inst was created through attach. + inst.deployTransaction = proxyDeployment.deployTransaction; + return inst.runner ? (inst as zk.Contract) : (inst.connect(wallet) as zk.Contract); } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts index 6a76a41fd..084e09f2b 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts @@ -5,13 +5,26 @@ import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import chalk from 'chalk'; import assert from 'assert'; -import { ContractAddressOrInstance, extractFactoryDeps, getContractAddress } from '../utils/utils-general'; +import { + ContractAddressOrInstance, + extractFactoryDeps, + getArtifactFromBytecode, + getContractAddress, +} from '../utils/utils-general'; import { UpgradeBeaconOptions } from '../utils/options'; import { deployBeaconImpl } from '../proxy-deployment/deploy-impl'; import { UPGRADABLE_BEACON_JSON } from '../constants'; +import { ZkSyncUpgradablePluginError } from '../errors'; import { getUpgradableContracts } from '../utils'; -export type UpgradeBeaconFunction = ( +export type UpgradeBeaconFactory = ( + beacon: ContractAddressOrInstance, + factory: zk.ContractFactory, + opts?: UpgradeBeaconOptions, + quiet?: boolean, +) => Promise; + +export type UpgradeBeaconArtifact = ( wallet: zk.Wallet, beacon: ContractAddressOrInstance, artifact: ZkSyncArtifact, @@ -19,47 +32,82 @@ export type UpgradeBeaconFunction = ( quiet?: boolean, ) => Promise; -export function makeUpgradeBeacon(hre: HardhatRuntimeEnvironment): UpgradeBeaconFunction { - return async function upgradeBeacon( - wallet, - beaconImplementation, - newImplementationArtifact, - opts: UpgradeBeaconOptions = {}, - quiet: boolean = false, - ) { - const factory = new zk.ContractFactory( - newImplementationArtifact.abi, - newImplementationArtifact.bytecode, - wallet, - opts.deploymentType, - ); +export async function upgradeBeaconFactory( + hre: HardhatRuntimeEnvironment, + beacon: ContractAddressOrInstance, + factory: zk.ContractFactory, + opts?: UpgradeBeaconOptions, + quiet?: boolean, +): Promise { + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) { + throw new ZkSyncUpgradablePluginError('Wallet is required for upgrade.'); + } - opts.provider = wallet.provider; - opts.factoryDeps = await extractFactoryDeps(hre, newImplementationArtifact); + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); - const beaconImplementationAddress = await getContractAddress(beaconImplementation); - const { impl: nextImpl } = await deployBeaconImpl(hre, factory, opts, beaconImplementationAddress); - if (!quiet) { - console.info(chalk.green('New beacon impl deployed at', nextImpl)); - } + return upgradeBeacon(hre, wallet, beacon, factory, opts, quiet); +} - const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), - ); - assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); - const upgradeableBeaconContract = await import(upgradableBeaconPath); +export async function upgradeBeaconArtifact( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + beacon: ContractAddressOrInstance, + artifact: ZkSyncArtifact, + opts?: UpgradeBeaconOptions, + quiet?: boolean, +): Promise { + const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, artifact as ZkSyncArtifact); + + return upgradeBeacon(hre, wallet, beacon, factory, opts, quiet); +} + +async function upgradeBeacon( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + beaconImplementation: ContractAddressOrInstance, + newImplementationFactory: zk.ContractFactory, + opts: UpgradeBeaconOptions = {}, + quiet: boolean = false, +) { + const beaconImplementationAddress = await getContractAddress(beaconImplementation); + const { impl: nextImpl } = await deployBeaconImpl(hre, newImplementationFactory, opts, beaconImplementationAddress); + if (!quiet) { + console.info(chalk.green('New beacon impl deployed at', nextImpl)); + } + + const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), + ); + assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); + const upgradeableBeaconContract = await import(upgradableBeaconPath); + + const upgradeableBeaconFactory = new zk.ContractFactory( + upgradeableBeaconContract.abi, + upgradeableBeaconContract.bytecode, + wallet, + ); - const upgradeableBeaconFactory = new zk.ContractFactory( - upgradeableBeaconContract.abi, - upgradeableBeaconContract.bytecode, - wallet, - ); + const beaconContract = upgradeableBeaconFactory.attach(beaconImplementationAddress); + const upgradeTx = await beaconContract.upgradeTo(nextImpl); - const beaconContract = upgradeableBeaconFactory.attach(beaconImplementationAddress); - const upgradeTx = await beaconContract.upgradeTo(nextImpl); + // @ts-ignore Won't be readonly because beaconContract was created through attach. + beaconContract.deployTransaction = upgradeTx; + return beaconContract; +} - // @ts-ignore Won't be readonly because beaconContract was created through attach. - beaconContract.deployTransaction = upgradeTx; - return beaconContract; +export function makeUpgradeBeacon(hre: HardhatRuntimeEnvironment): UpgradeBeaconArtifact | UpgradeBeaconFactory { + return async function (...args: Parameters): Promise { + const target = args[0]; + if (target instanceof zk.ContractFactory) { + return await upgradeBeaconFactory(hre, ...(args as Parameters)); + } else { + return upgradeBeaconArtifact(hre, ...(args as Parameters)); + } }; } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts index 48a68c423..ef6b08753 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts @@ -10,13 +10,21 @@ import chalk from 'chalk'; import assert from 'assert'; import { ContractAddressOrInstance } from '../interfaces'; import { UpgradeProxyOptions } from '../utils/options'; -import { extractFactoryDeps, getContractAddress } from '../utils/utils-general'; +import { extractFactoryDeps, getArtifactFromBytecode, getContractAddress } from '../utils/utils-general'; import { deployProxyImpl } from '../proxy-deployment/deploy-impl'; import { Manifest } from '../core/manifest'; import { ITUP_JSON, PROXY_ADMIN_JSON } from '../constants'; +import { ZkSyncUpgradablePluginError } from '../errors'; import { getUpgradableContracts } from '../utils'; -export type UpgradeFunction = ( +export type UpgradeProxyFactory = ( + proxy: ContractAddressOrInstance, + factory: zk.ContractFactory, + opts?: UpgradeProxyOptions, + quiet?: boolean, +) => Promise; + +export type UpgradeProxyArtifact = ( wallet: zk.Wallet, proxy: ContractAddressOrInstance, artifact: ZkSyncArtifact, @@ -24,88 +32,121 @@ export type UpgradeFunction = ( quiet?: boolean, ) => Promise; -export function makeUpgradeProxy(hre: HardhatRuntimeEnvironment): UpgradeFunction { - return async function upgradeProxy( - wallet, - proxy, - newImplementationArtifact, - opts: UpgradeProxyOptions = {}, - quiet: boolean = false, - ): Promise { - const proxyAddress = await getContractAddress(proxy); - opts.provider = wallet.provider; - opts.factoryDeps = await extractFactoryDeps(hre, newImplementationArtifact); - - const newImplementationFactory = new zk.ContractFactory( - newImplementationArtifact.abi, - newImplementationArtifact.bytecode, - wallet, - opts.deploymentType, - ); - const { impl: nextImpl } = await deployProxyImpl(hre, newImplementationFactory, opts, proxyAddress); - - const upgradeTo = await getUpgrader(proxyAddress, wallet); - const call = encodeCall(newImplementationFactory, opts.call); - const upgradeTx = await upgradeTo(nextImpl, call); +type Upgrader = (nextImpl: string, call?: string) => Promise; - if (!quiet) { - console.info(chalk.green(`Contract successfully upgraded to ${nextImpl} with tx ${upgradeTx.hash}`)); +export function makeUpgradeProxy(hre: HardhatRuntimeEnvironment): UpgradeProxyFactory | UpgradeProxyArtifact { + return async function (...args: Parameters): Promise { + const target = args[0]; + if (target instanceof zk.ContractFactory || args[1] instanceof zk.ContractFactory) { + return await upgradeProxyFactory(hre, ...(args as Parameters)); + } else { + return upgradeProxyArtifact(hre, ...(args as Parameters)); } - - const inst = newImplementationFactory.attach(proxyAddress); - // @ts-ignore Won't be readonly because inst was created through attach. - inst.deployTransaction = upgradeTx; - return inst; }; +} - type Upgrader = (nextImpl: string, call?: string) => Promise; +export async function upgradeProxyFactory( + hre: HardhatRuntimeEnvironment, + proxy: ContractAddressOrInstance, + factory: zk.ContractFactory, + opts?: UpgradeProxyOptions, + quiet?: boolean, +): Promise { + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) { + throw new ZkSyncUpgradablePluginError('Wallet is required for upgrade.'); + } - async function getUpgrader(proxyAddress: string, wallet: zk.Wallet): Promise { - const provider = wallet.provider as zk.Provider; + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); + return upgradeProxy(hre, wallet, proxy, factory, opts, quiet); +} - const adminAddress = await getAdminAddress(provider, proxyAddress); - const adminBytecode = await getCode(provider, adminAddress); +export async function upgradeProxyArtifact( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + proxy: ContractAddressOrInstance, + artifact: ZkSyncArtifact, + opts?: UpgradeProxyOptions, + quiet?: boolean, +): Promise { + const factory = new zk.ContractFactory(artifact.abi, artifact.bytecode, wallet); + opts = opts || {}; + opts.provider = wallet.provider; + opts.factoryDeps = await extractFactoryDeps(hre, artifact as ZkSyncArtifact); + return upgradeProxy(hre, wallet, proxy, factory, opts, quiet); +} - if (isEmptySlot(adminAddress) || adminBytecode === '0x') { - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + ITUP_JSON), - ); - assert(TUPPath, 'Transparent upgradeable proxy artifact not found'); - const transparentUpgradeableProxyContract = await import(TUPPath); +async function upgradeProxy( + hre: HardhatRuntimeEnvironment, + wallet: zk.Wallet, + proxy: ContractAddressOrInstance, + factory: zk.ContractFactory, + opts: UpgradeProxyOptions = {}, + quiet: boolean = false, +) { + const proxyAddress = await getContractAddress(proxy); - const transparentUpgradeableProxyFactory = new zk.ContractFactory( - transparentUpgradeableProxyContract.abi, - transparentUpgradeableProxyContract.bytecode, - wallet, - ); - const proxy = transparentUpgradeableProxyFactory.attach(proxyAddress); + const { impl: nextImpl } = await deployProxyImpl(hre, factory, opts, proxyAddress); - return (nextImpl, call) => (call ? proxy.upgradeToAndCall(nextImpl, call) : proxy.upgradeTo(nextImpl)); - } else { - const manifest = await Manifest.forNetwork(provider); + const upgradeTo = await getUpgrader(hre, proxyAddress, wallet); + const call = encodeCall(factory, opts.call); + const upgradeTx = await upgradeTo(nextImpl, call); - const proxyAdminPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ProxyAdmin + path.sep + PROXY_ADMIN_JSON), - ); - assert(proxyAdminPath, 'Proxy admin artifact not found'); - const proxyAdminContract = await import(proxyAdminPath); + if (!quiet) { + console.info(chalk.green(`Contract successfully upgraded to ${nextImpl} with tx ${upgradeTx.hash}`)); + } + + const inst = factory.attach(proxyAddress); + // @ts-ignore Won't be readonly because inst was created through attach. + inst.deployTransaction = upgradeTx; + return inst as zk.Contract; +} - const proxyAdminFactory = new zk.ContractFactory( - proxyAdminContract.abi, - proxyAdminContract.bytecode, - wallet, - ); +async function getUpgrader(hre: HardhatRuntimeEnvironment, proxyAddress: string, wallet: zk.Wallet): Promise { + const provider = wallet.provider as zk.Provider; - const admin = proxyAdminFactory.attach(adminAddress); - const manifestAdmin = await manifest.getAdmin(); + const adminAddress = await getAdminAddress(provider, proxyAddress); + const adminBytecode = await getCode(provider, adminAddress); - if ((await admin.getAddress()) !== manifestAdmin?.address) { - throw new Error('Proxy admin is not the one registered in the network manifest'); - } + if (isEmptySlot(adminAddress) || adminBytecode === '0x') { + const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + ITUP_JSON)); + assert(TUPPath, 'Transparent upgradeable proxy artifact not found'); + const transparentUpgradeableProxyContract = await import(TUPPath); - return (nextImpl, call) => - call ? admin.upgradeAndCall(proxyAddress, nextImpl, call) : admin.upgrade(proxyAddress, nextImpl); + const transparentUpgradeableProxyFactory = new zk.ContractFactory( + transparentUpgradeableProxyContract.abi, + transparentUpgradeableProxyContract.bytecode, + wallet, + ); + const proxy = transparentUpgradeableProxyFactory.attach(proxyAddress); + + return (nextImpl, call) => (call ? proxy.upgradeToAndCall(nextImpl, call) : proxy.upgradeTo(nextImpl)); + } else { + const manifest = await Manifest.forNetwork(provider); + + const proxyAdminPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().ProxyAdmin + path.sep + PROXY_ADMIN_JSON), + ); + assert(proxyAdminPath, 'Proxy admin artifact not found'); + const proxyAdminContract = await import(proxyAdminPath); + + const proxyAdminFactory = new zk.ContractFactory( + proxyAdminContract.abi, + proxyAdminContract.bytecode, + wallet, + ); + + const admin = proxyAdminFactory.attach(adminAddress); + const manifestAdmin = await manifest.getAdmin(); + + if ((await admin.getAddress()) !== manifestAdmin?.address) { + throw new Error('Proxy admin is not the one registered in the network manifest'); } + + return (nextImpl, call) => + call ? admin.upgradeAndCall(proxyAddress, nextImpl, call) : admin.upgrade(proxyAddress, nextImpl); } } diff --git a/packages/hardhat-zksync-upgradable/src/type-extensions.ts b/packages/hardhat-zksync-upgradable/src/type-extensions.ts index 4af6e7134..10f44a629 100644 --- a/packages/hardhat-zksync-upgradable/src/type-extensions.ts +++ b/packages/hardhat-zksync-upgradable/src/type-extensions.ts @@ -1,8 +1,10 @@ import 'hardhat/types/runtime'; -import { HardhatUpgrades } from './interfaces'; +import { DefenderHardhatUpgrades, HardhatUpgrades, HardhatZksyncUpgrades } from './interfaces'; declare module 'hardhat/types/runtime' { export interface HardhatRuntimeEnvironment { - zkUpgrades: HardhatUpgrades; + zkUpgrades: HardhatZksyncUpgrades; + upgrades: HardhatZksyncUpgrades & HardhatUpgrades; + defender: DefenderHardhatUpgrades | undefined; } } diff --git a/packages/hardhat-zksync-upgradable/src/utils/utils-general.ts b/packages/hardhat-zksync-upgradable/src/utils/utils-general.ts index f80dafbe2..1effc31a5 100644 --- a/packages/hardhat-zksync-upgradable/src/utils/utils-general.ts +++ b/packages/hardhat-zksync-upgradable/src/utils/utils-general.ts @@ -184,3 +184,17 @@ export async function extractFactoryDepsRecursive( return factoryDeps; } + +export async function getArtifactFromBytecode( + hre: HardhatRuntimeEnvironment, + bytecode: string, +): Promise { + const names = await hre.artifacts.getAllFullyQualifiedNames(); + for (const name of names) { + const artifact = await hre.artifacts.readArtifact(name); + if (artifact.bytecode === bytecode) { + return artifact as ZkSyncArtifact; + } + } + throw new ZkSyncUpgradablePluginError('Artifact for provided bytecode is not found.'); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3825ffbef..883f0ca93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -431,6 +431,91 @@ importers: '@matterlabs/hardhat-zksync-deploy': specifier: workspace:^ version: link:../../packages/hardhat-zksync-deploy + '@matterlabs/hardhat-zksync-ethers': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-ethers + '@matterlabs/hardhat-zksync-solc': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-solc + '@matterlabs/hardhat-zksync-upgradable': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-upgradable + '@matterlabs/hardhat-zksync-verify': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-verify + '@nomicfoundation/hardhat-ethers': + specifier: 3.0.6 + version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@openzeppelin/contracts-upgradeable': + specifier: ^4.9.2 + version: 4.9.6 + '@openzeppelin/hardhat-upgrades': + specifier: ^3.2.1 + version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + chalk: + specifier: ^4.1.2 + version: 4.1.2 + ethers: + specifier: ^6.12.2 + version: 6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + hardhat: + specifier: ^2.22.5 + version: 2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + zksync: + specifier: ^0.13.1 + version: 0.13.1(@ethersproject/logger@5.7.0)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + zksync-ethers: + specifier: ^6.8.0 + version: 6.8.0(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + devDependencies: + '@openzeppelin/contracts': + specifier: ^4.9.2 + version: 4.9.6 + '@types/node': + specifier: ^18.11.17 + version: 18.19.33 + '@typescript-eslint/eslint-plugin': + specifier: 6.13.1 + version: 6.13.1(@typescript-eslint/parser@6.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': + specifier: 6.13.1 + version: 6.13.1(eslint@8.57.0)(typescript@5.4.5) + eslint: + specifier: ^8.56.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-import: + specifier: ^2.29.1 + version: 2.29.1(@typescript-eslint/parser@6.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) + eslint-plugin-no-only-tests: + specifier: ^3.1.0 + version: 3.1.0 + eslint-plugin-prettier: + specifier: ^5.0.1 + version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.0) + prettier: + specifier: ^3.3.0 + version: 3.3.0 + rimraf: + specifier: ^5.0.7 + version: 5.0.7 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.33)(typescript@5.4.5) + typescript: + specifier: ^5.3.0 + version: 5.4.5 + + examples/upgradable-example-l1: + dependencies: + '@matterlabs/hardhat-zksync-deploy': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-deploy + '@matterlabs/hardhat-zksync-ethers': + specifier: workspace:^ + version: link:../../packages/hardhat-zksync-ethers '@matterlabs/hardhat-zksync-solc': specifier: workspace:^ version: link:../../packages/hardhat-zksync-solc @@ -440,6 +525,9 @@ importers: '@matterlabs/hardhat-zksync-verify': specifier: workspace:^ version: link:../../packages/hardhat-zksync-verify + '@nomicfoundation/hardhat-ethers': + specifier: 3.0.6 + version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts-upgradeable': specifier: ^4.9.2 version: 4.9.6 @@ -1248,6 +1336,9 @@ importers: '@openzeppelin/contracts-hardhat-zksync-upgradable': specifier: npm:@openzeppelin/contracts@^4.9.2 version: '@openzeppelin/contracts@4.9.6' + '@openzeppelin/hardhat-upgrades': + specifier: ^3.2.1 + version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/upgrades-core': specifier: ^1.31.3 version: 1.33.1 @@ -1624,6 +1715,19 @@ packages: '@adraffy/ens-normalize@1.10.1': resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==, tarball: https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz} + '@aws-crypto/sha256-js@1.2.2': + resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==, tarball: https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz} + + '@aws-crypto/util@1.2.2': + resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==, tarball: https://registry.npmjs.org/@aws-crypto/util/-/util-1.2.2.tgz} + + '@aws-sdk/types@3.609.0': + resolution: {integrity: sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==, tarball: https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==, tarball: https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz} + '@babel/code-frame@7.24.6': resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==, tarball: https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz} engines: {node: '>=6.9.0'} @@ -1937,6 +2041,46 @@ packages: peerDependencies: hardhat: ^2.0.4 + '@nomicfoundation/slang-darwin-arm64@0.15.1': + resolution: {integrity: sha512-taPHlCUNNztQZJze9OlZFK9cZH8Ut4Ih4QJQo5CKebXx9vWOUtmSBfKv/M2P8hiV/iL7Q5sPwR7HY9uZYnb49Q==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-darwin-x64@0.15.1': + resolution: {integrity: sha512-kgZh5KQe/UcbFqn1EpyrvBuT8E6I1kWSgGPtO25t90zAqFv23sMUPdn7wLpMjngkD+quIIgrzQGUtupS5YYEig==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-arm64-gnu@0.15.1': + resolution: {integrity: sha512-Iw8mepaccKRWllPU9l+hoe88LN9fScC0Px3nFeNQy26qk1ueO0tjovP1dhTvmGwHUxacOYPqhQTUn7Iu0oxNoQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-arm64-musl@0.15.1': + resolution: {integrity: sha512-zcesdQZwRgrT7ND+3TZUjRK/uGF20EfhEfCg8ZMhrb4Q7XaK1JvtHazIs03TV8Jcs30TPkEXks8Qi0Zdfy4RuA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-x64-gnu@0.15.1': + resolution: {integrity: sha512-FSmAnzKm58TFIwx4r/wOZtqfDx0nI6AfvnOh8kLDF5OxpWW3r0q9fq8lyaUReg9C/ZgCZRBn+m5WGrNKCZcvPQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-x64-musl@0.15.1': + resolution: {integrity: sha512-hnoA/dgeHQ8aS0SReABYkxf0d/Q6DdaKsaYv6ev21wyQA7TROxT1X3nekECLGu1GYLML8pzvD9vyAMBRKOkkyg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-arm64-msvc@0.15.1': + resolution: {integrity: sha512-2H0chHQ4uTh4l4UxN5fIVHR5mKaL5mfYTID6kxxxv2+KAh68EpYWwxLlkS5So90R2WcuPvFvTVKLm/uRo4h4dg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-ia32-msvc@0.15.1': + resolution: {integrity: sha512-CVZWBnbpFlVBg/m7bsiw70jY3p9TGH9vxq0vLEEJ56yK+QPosxPrKMcADojtGjIOjWjPSZ+lCoo5ilnW0a249g==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-x64-msvc@0.15.1': + resolution: {integrity: sha512-cyER8M1fdBTzIfihy55d4LGGlN/eQxDqfRUTXgJf1VvNR98tRB0Q3nBfyh5PK2yP98B4lMt3RJYDqTQu+dOVDA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.15.1.tgz} + engines: {node: '>= 10'} + + '@nomicfoundation/slang@0.15.1': + resolution: {integrity: sha512-th7nxRWRXf583uHpWUCd8U7BYxIqJX2f3oZLff/mlPkqIr45pD2hLT/o00eCjrBIR8N7vybUULZg1CeThGNk7g==, tarball: https://registry.npmjs.org/@nomicfoundation/slang/-/slang-0.15.1.tgz} + engines: {node: '>= 10'} + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': resolution: {integrity: sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==, tarball: https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz} engines: {node: '>= 10'} @@ -2019,10 +2163,35 @@ packages: '@openzeppelin/contracts@4.9.6': resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz} + '@openzeppelin/defender-sdk-base-client@1.14.3': + resolution: {integrity: sha512-4yG9E8N1c/ZP2jNR+Ah19wi7SBKpauAV/VcYcm7rg1dltDbzbH/oZnnXJlymT7IfjTPXkKHW8TPsaqz3EjS7tA==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.3.tgz} + + '@openzeppelin/defender-sdk-deploy-client@1.14.3': + resolution: {integrity: sha512-51WIZJz251lndK7uQU4gBE0gBX+2ZNTgf+hemtJUEPCpHtkooBRFFMID3EPGMKXVqf872pU8K3Huu9PyYQu6bw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.3.tgz} + + '@openzeppelin/defender-sdk-network-client@1.14.3': + resolution: {integrity: sha512-qrJLs2ubKSwrhP0x4V2QOPhlc1q8TYnkAcvjvk34VXMS8lhY1cpXSGoxnTw3Mi+eCSE1xOzKWISLi1UAOQOJIw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.14.3.tgz} + + '@openzeppelin/hardhat-upgrades@3.2.1': + resolution: {integrity: sha512-Zy5M3QhkzwGdpzQmk+xbWdYOGJWjoTvwbBKYLhctu9B91DoprlhDRaZUwCtunwTdynkTDGdVfGr0kIkvycyKjw==, tarball: https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.2.1.tgz} + hasBin: true + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^2.0.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + '@nomicfoundation/hardhat-verify': + optional: true + '@openzeppelin/upgrades-core@1.33.1': resolution: {integrity: sha512-YRxIRhTY1b+j7+NUUu8Uuem5ugxKexEMVd8dBRWNgWeoN1gS1OCrhgUg0ytL+54vzQ+SGWZDfNnzjVuI1Cj1Zw==, tarball: https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.33.1.tgz} hasBin: true + '@openzeppelin/upgrades-core@1.35.0': + resolution: {integrity: sha512-XwwhJyPxACQ7rMhKAPCL6rhTXhbeumeQ3opmurEsHg025vHnISHwTPHd5VxzmOwbMBIJ7em1lnRTu+J2/IUWFQ==, tarball: https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.35.0.tgz} + hasBin: true + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz} engines: {node: '>=14'} @@ -2083,6 +2252,10 @@ packages: '@sinonjs/text-encoding@0.7.2': resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==, tarball: https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz} + '@smithy/types@3.3.0': + resolution: {integrity: sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==, tarball: https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz} + engines: {node: '>=16.0.0'} + '@ts-morph/common@0.23.0': resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==, tarball: https://registry.npmjs.org/@ts-morph/common/-/common-0.23.0.tgz} @@ -2370,6 +2543,9 @@ packages: ajv@8.14.0: resolution: {integrity: sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==, tarball: https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz} + amazon-cognito-identity-js@6.3.12: + resolution: {integrity: sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==, tarball: https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==, tarball: https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz} @@ -2476,6 +2652,9 @@ packages: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, tarball: https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz} engines: {node: '>=8'} + async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==, tarball: https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, tarball: https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz} @@ -2574,6 +2753,9 @@ packages: buffer-xor@1.0.3: resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==, tarball: https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz} + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==, tarball: https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, tarball: https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz} @@ -3182,6 +3364,9 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==, tarball: https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz} engines: {node: '>=4'} + fast-base64-decode@1.0.0: + resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==, tarball: https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, tarball: https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz} @@ -3641,6 +3826,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, tarball: https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz} + isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==, tarball: https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz} + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, tarball: https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz} engines: {node: '>=8'} @@ -3661,6 +3849,9 @@ packages: resolution: {integrity: sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==, tarball: https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz} engines: {node: '>= 6'} + js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==, tarball: https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz} + js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==, tarball: https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz} @@ -4273,6 +4464,10 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==, tarball: https://registry.npmjs.org/retry/-/retry-0.12.0.tgz} engines: {node: '>= 4'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==, tarball: https://registry.npmjs.org/retry/-/retry-0.13.1.tgz} + engines: {node: '>= 4'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, tarball: https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -4743,6 +4938,9 @@ packages: resolution: {integrity: sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==, tarball: https://registry.npmjs.org/undici/-/undici-6.18.2.tgz} engines: {node: '>=18.17'} + unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==, tarball: https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==, tarball: https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz} engines: {node: '>= 4.0.0'} @@ -4961,6 +5159,27 @@ snapshots: '@adraffy/ens-normalize@1.10.1': {} + '@aws-crypto/sha256-js@1.2.2': + dependencies: + '@aws-crypto/util': 1.2.2 + '@aws-sdk/types': 3.609.0 + tslib: 1.14.1 + + '@aws-crypto/util@1.2.2': + dependencies: + '@aws-sdk/types': 3.609.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + + '@aws-sdk/types@3.609.0': + dependencies: + '@smithy/types': 3.3.0 + tslib: 2.6.2 + + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.6.2 + '@babel/code-frame@7.24.6': dependencies: '@babel/highlight': 7.24.6 @@ -5465,6 +5684,36 @@ snapshots: transitivePeerDependencies: - supports-color + '@nomicfoundation/slang-darwin-arm64@0.15.1': {} + + '@nomicfoundation/slang-darwin-x64@0.15.1': {} + + '@nomicfoundation/slang-linux-arm64-gnu@0.15.1': {} + + '@nomicfoundation/slang-linux-arm64-musl@0.15.1': {} + + '@nomicfoundation/slang-linux-x64-gnu@0.15.1': {} + + '@nomicfoundation/slang-linux-x64-musl@0.15.1': {} + + '@nomicfoundation/slang-win32-arm64-msvc@0.15.1': {} + + '@nomicfoundation/slang-win32-ia32-msvc@0.15.1': {} + + '@nomicfoundation/slang-win32-x64-msvc@0.15.1': {} + + '@nomicfoundation/slang@0.15.1': + dependencies: + '@nomicfoundation/slang-darwin-arm64': 0.15.1 + '@nomicfoundation/slang-darwin-x64': 0.15.1 + '@nomicfoundation/slang-linux-arm64-gnu': 0.15.1 + '@nomicfoundation/slang-linux-arm64-musl': 0.15.1 + '@nomicfoundation/slang-linux-x64-gnu': 0.15.1 + '@nomicfoundation/slang-linux-x64-musl': 0.15.1 + '@nomicfoundation/slang-win32-arm64-msvc': 0.15.1 + '@nomicfoundation/slang-win32-ia32-msvc': 0.15.1 + '@nomicfoundation/slang-win32-x64-msvc': 0.15.1 + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': optional: true @@ -5536,6 +5785,51 @@ snapshots: '@openzeppelin/contracts@4.9.6': {} + '@openzeppelin/defender-sdk-base-client@1.14.3': + dependencies: + amazon-cognito-identity-js: 6.3.12 + async-retry: 1.3.3 + transitivePeerDependencies: + - encoding + + '@openzeppelin/defender-sdk-deploy-client@1.14.3(debug@4.3.5)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.14.3 + axios: 1.7.2(debug@4.3.5) + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-network-client@1.14.3(debug@4.3.5)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.14.3 + axios: 1.7.2(debug@4.3.5) + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/hardhat-upgrades@3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@openzeppelin/defender-sdk-base-client': 1.14.3 + '@openzeppelin/defender-sdk-deploy-client': 1.14.3(debug@4.3.5) + '@openzeppelin/defender-sdk-network-client': 1.14.3(debug@4.3.5) + '@openzeppelin/upgrades-core': 1.35.0 + chalk: 4.1.2 + debug: 4.3.5 + ethereumjs-util: 7.1.5 + ethers: 6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + hardhat: 2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + proper-lockfile: 4.1.2 + undici: 6.18.2 + optionalDependencies: + '@nomicfoundation/hardhat-verify': 2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + transitivePeerDependencies: + - encoding + - supports-color + '@openzeppelin/upgrades-core@1.33.1': dependencies: cbor: 9.0.2 @@ -5549,6 +5843,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@openzeppelin/upgrades-core@1.35.0': + dependencies: + '@nomicfoundation/slang': 0.15.1 + cbor: 9.0.2 + chalk: 4.1.2 + compare-versions: 6.1.0 + debug: 4.3.5 + ethereumjs-util: 7.1.5 + minimist: 1.2.8 + proper-lockfile: 4.1.2 + solidity-ast: 0.4.56 + transitivePeerDependencies: + - supports-color + '@pkgjs/parseargs@0.11.0': optional: true @@ -5636,6 +5944,10 @@ snapshots: '@sinonjs/text-encoding@0.7.2': {} + '@smithy/types@3.3.0': + dependencies: + tslib: 2.6.2 + '@ts-morph/common@0.23.0': dependencies: fast-glob: 3.3.2 @@ -5984,6 +6296,16 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 + amazon-cognito-identity-js@6.3.12: + dependencies: + '@aws-crypto/sha256-js': 1.2.2 + buffer: 4.9.2 + fast-base64-decode: 1.0.0 + isomorphic-unfetch: 3.1.0 + js-cookie: 2.2.1 + transitivePeerDependencies: + - encoding + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -6100,6 +6422,10 @@ snapshots: astral-regex@2.0.0: {} + async-retry@1.3.3: + dependencies: + retry: 0.13.1 + asynckit@0.4.0: {} available-typed-arrays@1.0.7: @@ -6221,6 +6547,12 @@ snapshots: buffer-xor@1.0.3: {} + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -7080,6 +7412,8 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-base64-decode@1.0.0: {} + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -7587,6 +7921,13 @@ snapshots: isexe@2.0.0: {} + isomorphic-unfetch@3.1.0: + dependencies: + node-fetch: 2.7.0 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -7612,6 +7953,8 @@ snapshots: execa: 1.0.0 throat: 4.1.0 + js-cookie@2.2.1: {} + js-sha3@0.8.0: {} js-tokens@4.0.0: {} @@ -8225,6 +8568,8 @@ snapshots: retry@0.12.0: {} + retry@0.13.1: {} + reusify@1.0.4: {} rimraf@2.7.1: @@ -8739,6 +9084,8 @@ snapshots: undici@6.18.2: {} + unfetch@4.2.0: {} + universalify@0.1.2: {} universalify@2.0.1: {} From 54e59aaccb961a8ea65861e51961c06ee2e2dcba Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Wed, 7 Aug 2024 15:25:12 +0200 Subject: [PATCH 02/20] chore: apply lint --- .github/workflows/ci.yml | 1 - .../src/proxy-upgrade/upgrade-proxy.ts | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 441eddf14..6e41fa375 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,7 +196,6 @@ jobs: pnpm hardhat run scripts/deploy-box-proxy-factory.ts pnpm hardhat run scripts/deploy-box-uups-factory.ts pnpm hardhat run scripts/upgrade-box-beacon-factory.ts - pnpm hardhat run scripts/upgrade-box-uups-factory.ts pnpm hardhat run scripts/upgrade-box-factory.ts - name: Test upgradable example diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts index ef6b08753..ab29da370 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts @@ -111,7 +111,9 @@ async function getUpgrader(hre: HardhatRuntimeEnvironment, proxyAddress: string, const adminBytecode = await getCode(provider, adminAddress); if (isEmptySlot(adminAddress) || adminBytecode === '0x') { - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + ITUP_JSON)); + const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + ITUP_JSON), + ); assert(TUPPath, 'Transparent upgradeable proxy artifact not found'); const transparentUpgradeableProxyContract = await import(TUPPath); From a458d7cd5b561a8cdf6735a4e4a55e6613872443 Mon Sep 17 00:00:00 2001 From: nikola-bozin-txfusion Date: Wed, 7 Aug 2024 16:07:22 +0200 Subject: [PATCH 03/20] fix: add additional example and remove unnessecary file --- .github/workflows/ci.yml | 1 + .../.openzeppelin/sepolia.json | 338 ------------------ examples/upgradable-example/hardhat.config.ts | 7 +- .../scripts/upgrade-box-uups-factory.ts | 36 ++ 4 files changed, 39 insertions(+), 343 deletions(-) delete mode 100644 examples/upgradable-example-l1/.openzeppelin/sepolia.json create mode 100644 examples/upgradable-example/scripts/upgrade-box-uups-factory.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e41fa375..0c1a96ce5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,6 +195,7 @@ jobs: pnpm hardhat run scripts/deploy-box-beacon-factory.ts pnpm hardhat run scripts/deploy-box-proxy-factory.ts pnpm hardhat run scripts/deploy-box-uups-factory.ts + pnpm hardhat run scripts/upgrade-box-uups-factory.ts pnpm hardhat run scripts/upgrade-box-beacon-factory.ts pnpm hardhat run scripts/upgrade-box-factory.ts diff --git a/examples/upgradable-example-l1/.openzeppelin/sepolia.json b/examples/upgradable-example-l1/.openzeppelin/sepolia.json deleted file mode 100644 index 071b8fa9f..000000000 --- a/examples/upgradable-example-l1/.openzeppelin/sepolia.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "manifestVersion": "3.2", - "proxies": [ - { - "address": "0xE8a5dD63426D1C05B16ecd4D950C7E7BA5420Fe1", - "txHash": "0x663597fdbe68f11c887330a0e7d6fb432130e1b3fddf8b4838a338816bb03d76", - "kind": "beacon" - }, - { - "address": "0xA48677C93eB9D3B62cc5FE54C63a6B64Cc64A5f6", - "txHash": "0x6ef386d245e39b307cffcd4bf98ee1775ab4ba1fdf4d353c6305e06a8a945738", - "kind": "transparent" - }, - { - "address": "0xA4f938Ba130956467aC5D9D9424dc1c67508d7AB", - "txHash": "0x1d9447ba1235c1e715033d2aadf07f1d927d9dde2473d9197479ee98ec97a742", - "kind": "uups" - }, - { - "address": "0xfa83abe364c47196E24Bc1A9ed537d62Cf30Cf9F", - "txHash": "0x76b73c7c6916dd4c6f61ce129d7ac4a09e00c9544688ac225506444cb214d8e9", - "kind": "beacon" - }, - { - "address": "0xEaB1F8a85c0bF6Bc047D7F2251485216cb38BC23", - "txHash": "0xbeff40e65090150a7a2b5dd32dee19c3ce750acd16ac5968077fcc93cc089efa", - "kind": "transparent" - }, - { - "address": "0x4e9282a22189Cb2dFAd28D1e2277Ab4A6A7F79B9", - "txHash": "0x169c71730bce649106702513d53cb2d9976901b5a7449f89935fcf26eaf6b209", - "kind": "transparent" - }, - { - "address": "0x1DEe5f4D6b9bc71CD79d0f1780451f2f7Ae85C9e", - "txHash": "0x5c9a1e4027f02d7f171f2da1d9f9e06e705f4d26c3e4c7720b54c4445aee96b6", - "kind": "uups" - }, - { - "address": "0x925bc6D3A26F28fD960e3Da2CF8f19524dEC8DC7", - "txHash": "0x2fab0ec9f872881549c39f4b56a2d485d57978e30ef80f33185935a222838a6d", - "kind": "uups" - }, - { - "address": "0x74EF4793372F97D0b4F1c2208BF0D72cf0F96f5C", - "txHash": "0x647c4741baceb72d75e14fcb2598ed6b15e67ebaabdeb21aa23f409773d1d439", - "kind": "uups" - } - ], - "impls": { - "bf966385854e3ede49da805ebbde0f3e9f882e4ba662ad33879278ae7fbfd484": { - "address": "0xA48cE32F2e6964EAADC4ED3af50A2a7E37599A87", - "txHash": "0xf3c5e2b3791e7376c42765c7e53409fd57ac2b6a02506677a8d48f4f9f836a1e", - "layout": { - "solcVersion": "0.8.20", - "storage": [ - { - "contract": "Initializable", - "label": "_initialized", - "type": "t_uint8", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "contract": "Initializable", - "label": "_initializing", - "type": "t_bool", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "contract": "Box", - "label": "value", - "type": "t_uint256", - "src": "contracts/Box.sol:7" - }, - { - "contract": "Box", - "label": "secondValue", - "type": "t_uint256", - "src": "contracts/Box.sol:8" - }, - { - "contract": "Box", - "label": "thirdValue", - "type": "t_uint256", - "src": "contracts/Box.sol:9" - } - ], - "types": { - "t_uint256": { - "label": "uint256" - }, - "t_uint8": { - "label": "uint8" - }, - "t_bool": { - "label": "bool" - } - }, - "namespaces": {} - } - }, - "90ddd0edfad2f9b7b3f66d0ec849d08c6cc48df12f23635e4e48bc017aceeb5e": { - "address": "0x8F59dbBc201951C61d38d507d7bEdFC50127B06e", - "txHash": "0xa2a6726ed6a8059c286f4d540443fd3d548a694567987b8013460e582c5ec004", - "layout": { - "solcVersion": "0.8.20", - "storage": [ - { - "contract": "Initializable", - "label": "_initialized", - "type": "t_uint8", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "contract": "Initializable", - "label": "_initializing", - "type": "t_bool", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "contract": "ERC1967UpgradeUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" - }, - { - "contract": "UUPSUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" - }, - { - "contract": "ContextUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" - }, - { - "contract": "OwnableUpgradeable", - "label": "_owner", - "type": "t_address", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "contract": "OwnableUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)49_storage", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "contract": "BoxUups", - "label": "value", - "type": "t_uint256", - "src": "contracts/BoxUups.sol:8" - }, - { - "contract": "BoxUups", - "label": "secondValue", - "type": "t_uint256", - "src": "contracts/BoxUups.sol:9" - }, - { - "contract": "BoxUups", - "label": "thirdValue", - "type": "t_uint256", - "src": "contracts/BoxUups.sol:10" - } - ], - "types": { - "t_uint256": { - "label": "uint256" - }, - "t_address": { - "label": "address" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]" - }, - "t_uint8": { - "label": "uint8" - }, - "t_bool": { - "label": "bool" - } - }, - "namespaces": {} - } - }, - "1786c31e6c8dd2320e37d96de50ff21bb880be3012ed8e01f26ceaaecd374176": { - "address": "0x6ee4960EeEe6c4Cb4ebA4eE08c27c2F693Da5017", - "txHash": "0x30005acfaaba243551cc990b852f3971ef7138407e1b4b12d225c7bfeb92a1e8", - "layout": { - "solcVersion": "0.8.20", - "storage": [ - { - "contract": "Initializable", - "label": "_initialized", - "type": "t_uint8", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "contract": "Initializable", - "label": "_initializing", - "type": "t_bool", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "contract": "BoxV2", - "label": "value", - "type": "t_uint256", - "src": "contracts/BoxV2.sol:7" - }, - { - "contract": "BoxV2", - "label": "secondValue", - "type": "t_uint256", - "src": "contracts/BoxV2.sol:8" - }, - { - "contract": "BoxV2", - "label": "thirdValue", - "type": "t_uint256", - "src": "contracts/BoxV2.sol:9" - } - ], - "types": { - "t_uint256": { - "label": "uint256" - }, - "t_uint8": { - "label": "uint8" - }, - "t_bool": { - "label": "bool" - } - }, - "namespaces": {} - } - }, - "c3202b9d264d74d50b5eea6eb203c1ae77d1e016958eb45bb06d48aeddadd823": { - "address": "0x3f3f76Dd75A55A30Af613c50318204f68E50Fe3B", - "txHash": "0xfba17a817fcd11dcb98c4478df8d0e2b41a92ea2a3238b82d98029204b8500d4", - "layout": { - "solcVersion": "0.8.20", - "storage": [ - { - "contract": "Initializable", - "label": "_initialized", - "type": "t_uint8", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "contract": "Initializable", - "label": "_initializing", - "type": "t_bool", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "contract": "ERC1967UpgradeUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" - }, - { - "contract": "UUPSUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" - }, - { - "contract": "ContextUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" - }, - { - "contract": "OwnableUpgradeable", - "label": "_owner", - "type": "t_address", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "contract": "OwnableUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)49_storage", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "contract": "BoxUupsV2", - "label": "value", - "type": "t_uint256", - "src": "contracts/BoxUupsV2.sol:8" - }, - { - "contract": "BoxUupsV2", - "label": "secondValue", - "type": "t_uint256", - "src": "contracts/BoxUupsV2.sol:9" - }, - { - "contract": "BoxUupsV2", - "label": "thirdValue", - "type": "t_uint256", - "src": "contracts/BoxUupsV2.sol:10" - } - ], - "types": { - "t_uint256": { - "label": "uint256" - }, - "t_address": { - "label": "address" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]" - }, - "t_uint8": { - "label": "uint8" - }, - "t_bool": { - "label": "bool" - } - }, - "namespaces": {} - } - } - } -} diff --git a/examples/upgradable-example/hardhat.config.ts b/examples/upgradable-example/hardhat.config.ts index 0b0f82983..edc37ccfa 100644 --- a/examples/upgradable-example/hardhat.config.ts +++ b/examples/upgradable-example/hardhat.config.ts @@ -17,17 +17,14 @@ const config: HardhatUserConfig = { }, }, }, + defaultNetwork:'zkSyncNetwork', networks: { hardhat: { zksync: true, }, - eth: { - zksync: true, - url: 'http://0.0.0.0:8545', - }, zkSyncNetwork: { zksync: true, - ethNetwork: 'eth', + ethNetwork: 'http://0.0.0.0:8545', url: 'http://0.0.0.0:3050', }, }, diff --git a/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts b/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts new file mode 100644 index 000000000..79f3a9522 --- /dev/null +++ b/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts @@ -0,0 +1,36 @@ +import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; +import { Wallet } from 'zksync-ethers'; +import chalk from 'chalk'; + +import * as hre from 'hardhat'; + +async function main() { + const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; + const zkWallet = Wallet.fromMnemonic(testMnemonic); + const deployer = new Deployer(hre, zkWallet); + + // deploy proxy + const contractName = 'BoxUups'; + + const boxFactory = await hre.zksyncEthers.getContractFactory(contractName, deployer.zkWallet); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize' }); + + await box.waitForDeployment(); + + // upgrade proxy implementation + + const BoxUupsV2Factory = await hre.zksyncEthers.getContractFactory('BoxUupsV2'); + const upgradedBox = await hre.upgrades.upgradeProxy(await box.getAddress(), BoxUupsV2Factory); + console.info(chalk.green('Successfully upgraded BoxUups to BoxUupsV2')); + + upgradedBox.connect(zkWallet); + // wait some time before the next call + await new Promise((resolve) => setTimeout(resolve, 2000)); + const value = await upgradedBox.retrieve(); + console.info(chalk.cyan('BoxUups value is', value)); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); From 04b7ba2bebb4bcfb09a7fbc3ca518dc5df799a2b Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 13 Aug 2024 16:37:05 +0200 Subject: [PATCH 04/20] fix: refactor code, adjust params and set proper version of that oz hardhat-upgradable plugin --- examples/upgradable-example/package.json | 2 +- .../scripts/deploy-box-beacon-factory.ts | 6 +- packages/hardhat-zksync-solc/src/index.ts | 4 + packages/hardhat-zksync-solc/src/types.ts | 4 +- .../hardhat-zksync-upgradable/package.json | 2 +- .../src/extension-generator.ts | 206 ++++++++++++ .../hardhat-zksync-upgradable/src/index.ts | 195 +----------- .../src/interfaces.ts | 133 +++++--- .../hardhat-zksync-upgradable/src/plugin.ts | 2 +- .../proxy-deployment/deploy-beacon-proxy.ts | 2 +- .../src/proxy-deployment/deploy-beacon.ts | 9 +- .../src/proxy-deployment/deploy-proxy.ts | 36 ++- .../src/type-extensions.ts | 6 +- .../hardhat-zksync-upgradable/src/utils.ts | 33 +- pnpm-lock.yaml | 297 ++++++++++++++++-- 15 files changed, 662 insertions(+), 275 deletions(-) create mode 100644 packages/hardhat-zksync-upgradable/src/extension-generator.ts diff --git a/examples/upgradable-example/package.json b/examples/upgradable-example/package.json index a3c6078f2..746a5f897 100644 --- a/examples/upgradable-example/package.json +++ b/examples/upgradable-example/package.json @@ -37,7 +37,7 @@ "@matterlabs/hardhat-zksync-verify": "workspace:^", "@nomicfoundation/hardhat-ethers": "3.0.6", "@openzeppelin/contracts-upgradeable": "^4.9.2", - "@openzeppelin/hardhat-upgrades": "^3.2.1", + "@openzeppelin/hardhat-upgrades": "^2.5.1", "chalk": "^4.1.2", "ethers": "^6.12.2", "hardhat": "^2.22.5", diff --git a/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts b/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts index 88f30f2d2..a3cd7133a 100644 --- a/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts +++ b/examples/upgradable-example/scripts/deploy-box-beacon-factory.ts @@ -20,11 +20,9 @@ async function main() { await beacon.waitForDeployment(); const box = await hre.upgrades.deployBeaconProxy( - deployer.zkWallet, await beacon.getAddress(), - boxArtifact, - [42], - {}, + boxFactory, + [42] ); await box.waitForDeployment(); diff --git a/packages/hardhat-zksync-solc/src/index.ts b/packages/hardhat-zksync-solc/src/index.ts index d01e420b5..0e4d4a260 100644 --- a/packages/hardhat-zksync-solc/src/index.ts +++ b/packages/hardhat-zksync-solc/src/index.ts @@ -193,6 +193,10 @@ subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, async (args: { sourcePaths: stri return await runSuper(args); } + if (hre.config.zksolc.settings.overrideContractsToCompile) { + return hre.config.zksolc.settings.overrideContractsToCompile; + } + const contractsToCompile: string[] | undefined = hre.config.zksolc.settings.contractsToCompile; if (!contractsToCompile || contractsToCompile.length === 0) { diff --git a/packages/hardhat-zksync-solc/src/types.ts b/packages/hardhat-zksync-solc/src/types.ts index 2e55929eb..8cbe2ae4b 100644 --- a/packages/hardhat-zksync-solc/src/types.ts +++ b/packages/hardhat-zksync-solc/src/types.ts @@ -40,8 +40,10 @@ export interface ZkSolcConfig { forceEvmla?: boolean; // Evmla intermediate representation forceEVMLA?: boolean; - // Specific contracts to be compiled + // Specific contracts present in source to be compiled contractsToCompile?: string[]; + // Specific only contracts forced to be compiled even if they are not present in source + overrideContractsToCompile?: string[]; // Dump all IR (Yul, EVMLA, LLVM IR, assembly) to files in the specified directory. Only for testing and debugging. debugOutputDir?: string; }; diff --git a/packages/hardhat-zksync-upgradable/package.json b/packages/hardhat-zksync-upgradable/package.json index 77993338c..8e411b4e0 100644 --- a/packages/hardhat-zksync-upgradable/package.json +++ b/packages/hardhat-zksync-upgradable/package.json @@ -36,7 +36,7 @@ "@matterlabs/hardhat-zksync-deploy": "workspace:^", "@matterlabs/hardhat-zksync-solc": "workspace:^", "@openzeppelin/contracts-hardhat-zksync-upgradable": "npm:@openzeppelin/contracts@^4.9.2", - "@openzeppelin/hardhat-upgrades": "^3.2.1", + "@openzeppelin/hardhat-upgrades": "~2.5.1", "@openzeppelin/upgrades-core": "^1.31.3", "chalk": "^4.1.2", "compare-versions": "^6.1.0", diff --git a/packages/hardhat-zksync-upgradable/src/extension-generator.ts b/packages/hardhat-zksync-upgradable/src/extension-generator.ts new file mode 100644 index 000000000..ad94fb3a5 --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/extension-generator.ts @@ -0,0 +1,206 @@ +import { lazyObject } from 'hardhat/plugins'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { tryRequire, wrapMakeFunction } from './utils'; +import { HardhatUpgradesOZ, HardhatZksyncUpgrades, makeUndefinedFunction } from './interfaces'; + +export class ExtensionGenerator { + constructor(private _hre: HardhatRuntimeEnvironment) {} + + public populateExtension(): void { + if (this._hre.network.zksync) { + const zkSyncGenerator = new ZkSyncGenerator(this._hre); + zkSyncGenerator.populateExtension(); + return; + } + + const ethersGenerators = new EthersGenerator(this._hre); + ethersGenerators.populateExtension(); + } +} + +interface Generator { + populateExtension(): void; +} + +class ZkSyncGenerator implements Generator { + constructor(private _hre: HardhatRuntimeEnvironment) {} + + public populateExtension(): void { + this._hre.upgrades = lazyObject(() => this.makeFunctions() as HardhatUpgradesOZ & HardhatZksyncUpgrades); + this._hre.zkUpgrades = lazyObject(() => this.makeFunctions()); + } + + private makeFunctions(): HardhatZksyncUpgrades { + const { makeDeployProxy } = require('./proxy-deployment/deploy-proxy'); + const { makeUpgradeProxy } = require('./proxy-upgrade/upgrade-proxy'); + const { makeValidateImplementation } = require('./validations/validate-implementation'); + const { makeDeployBeacon } = require('./proxy-deployment/deploy-beacon'); + const { makeDeployBeaconProxy } = require('./proxy-deployment/deploy-beacon-proxy'); + const { makeUpgradeBeacon } = require('./proxy-upgrade/upgrade-beacon'); + const { makeDeployProxyAdmin } = require('./proxy-deployment/deploy-proxy-admin'); + const { makeEstimateGasProxy } = require('./gas-estimation/estimate-gas-proxy'); + const { makeEstimateGasBeacon } = require('./gas-estimation/estimate-gas-beacon'); + const { makeEstimateGasBeaconProxy } = require('./gas-estimation/estimate-gas-beacon-proxy'); + const { makeGetInstanceFunction, makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); + return { + deployProxy: wrapMakeFunction(this._hre, makeDeployProxy(this._hre)), + upgradeProxy: wrapMakeFunction(this._hre, makeUpgradeProxy(this._hre)), + validateImplementation: wrapMakeFunction(this._hre, makeValidateImplementation(this._hre)), + deployBeacon: wrapMakeFunction(this._hre, makeDeployBeacon(this._hre)), + deployBeaconProxy: wrapMakeFunction(this._hre, makeDeployBeaconProxy(this._hre)), + upgradeBeacon: wrapMakeFunction(this._hre, makeUpgradeBeacon(this._hre)), + deployProxyAdmin: wrapMakeFunction(this._hre, makeDeployProxyAdmin(this._hre)), + admin: { + getInstance: wrapMakeFunction(this._hre, makeGetInstanceFunction(this._hre)), + changeProxyAdmin: wrapMakeFunction(this._hre, makeChangeProxyAdmin(this._hre)), + transferProxyAdminOwnership: wrapMakeFunction(this._hre, makeTransferProxyAdminOwnership(this._hre)), + }, + estimation: { + estimateGasProxy: wrapMakeFunction(this._hre, makeEstimateGasProxy(this._hre)), + estimateGasBeacon: wrapMakeFunction(this._hre, makeEstimateGasBeacon(this._hre)), + estimateGasBeaconProxy: wrapMakeFunction(this._hre, makeEstimateGasBeaconProxy(this._hre)), + }, + // Properties from oz-upgrades + forceImport: makeUndefinedFunction(), + silenceWarnings: makeUndefinedFunction(), + validateUpgrade: makeUndefinedFunction(), + deployImplementation: makeUndefinedFunction(), + prepareUpgrade: makeUndefinedFunction(), + beacon: { + getImplementationAddress: makeUndefinedFunction(), + }, + erc1967: { + getAdminAddress: makeUndefinedFunction(), + getImplementationAddress: makeUndefinedFunction(), + getBeaconAddress: makeUndefinedFunction(), + }, + }; + } +} + +class EthersGenerator implements Generator { + constructor(private _hre: HardhatRuntimeEnvironment) {} + + public populateExtension(): void { + this._hre.upgrades = lazyObject(() => this.makeFunctions(false) as HardhatUpgradesOZ & HardhatZksyncUpgrades); + this.warnOnHardhatDefender(); + this._hre.defender = lazyObject(() => this.makeDefenderFunctions()); + } + + private makeFunctions(defender: boolean): HardhatUpgradesOZ { + const { + getImplementationAddressFromBeacon, + silenceWarnings, + } = require('@openzeppelin/upgrades-core/dist/impl-address'); + const { + getAdminAddress, + getImplementationAddress, + getBeaconAddress, + } = require('@openzeppelin/upgrades-core/dist/eip-1967'); + const { makeDeployProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy'); + const { makeUpgradeProxy } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'); + const { makeValidateImplementation } = require('@openzeppelin/hardhat-upgrades/dist/validate-implementation'); + const { makeValidateUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/validate-upgrade'); + const { makeDeployImplementation } = require('@openzeppelin/hardhat-upgrades/dist/deploy-implementation'); + const { makePrepareUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'); + const { makeDeployBeacon } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon'); + const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); + const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); + const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); + const { makeDeployProxyAdmin } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'); + const { + makeChangeProxyAdmin, + makeTransferProxyAdminOwnership, + makeGetInstanceFunction, + } = require('@openzeppelin/hardhat-upgrades/dist/admin'); + + return { + silenceWarnings, + deployProxy: makeDeployProxy(this._hre, defender), + upgradeProxy: makeUpgradeProxy(this._hre, defender), // block on defender + validateImplementation: makeValidateImplementation(this._hre), + validateUpgrade: makeValidateUpgrade(this._hre), + deployImplementation: makeDeployImplementation(this._hre, defender), + prepareUpgrade: makePrepareUpgrade(this._hre, defender), + deployBeacon: makeDeployBeacon(this._hre, defender), // block on defender + deployBeaconProxy: makeDeployBeaconProxy(this._hre, defender), + deployProxyAdmin: makeDeployProxyAdmin(this._hre, defender), + upgradeBeacon: makeUpgradeBeacon(this._hre, defender), // block on defender + forceImport: makeForceImport(this._hre), + admin: { + getInstance: makeGetInstanceFunction(this._hre, defender), // block on defender + changeProxyAdmin: makeChangeProxyAdmin(this._hre, defender), // block on defender + transferProxyAdminOwnership: makeTransferProxyAdminOwnership(this._hre, defender), // block on defender + }, + erc1967: { + getAdminAddress: (proxyAddress: string) => getAdminAddress(this._hre.network.provider, proxyAddress), + getImplementationAddress: (proxyAddress: string) => + getImplementationAddress(this._hre.network.provider, proxyAddress), + getBeaconAddress: (proxyAddress: string) => getBeaconAddress(this._hre.network.provider, proxyAddress), + }, + beacon: { + getImplementationAddress: (beaconAddress: string) => + getImplementationAddressFromBeacon(this._hre.network.provider, beaconAddress), + }, + // Properties from zksync + estimation: { + estimateGasProxy: makeUndefinedFunction(), + estimateGasBeacon: makeUndefinedFunction(), + estimateGasBeaconProxy: makeUndefinedFunction(), + }, + }; + } + + private makeDefenderFunctions() { + const { makeDeployContract } = require('@openzeppelin/hardhat-upgrades/dist/deploy-contract'); + const { + makeProposeUpgradeWithApproval, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'); + const { + makeGetDeployApprovalProcess, + makeGetUpgradeApprovalProcess, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'); + + const getUpgradeApprovalProcess = makeGetUpgradeApprovalProcess(this._hre); + + return { + ...this.makeFunctions(true), + // ...this.makeDefenderV1Functions(), + deployContract: makeDeployContract(this._hre, true), + proposeUpgradeWithApproval: makeProposeUpgradeWithApproval(this._hre, true), + getDeployApprovalProcess: makeGetDeployApprovalProcess(this._hre), + getUpgradeApprovalProcess, + getDefaultApprovalProcess: getUpgradeApprovalProcess, // deprecated, is an alias for getUpgradeApprovalProcess + }; + } + + private makeDefenderV1Functions() { + const { + makeVerifyDeploy, + makeVerifyDeployWithUploadedArtifact, + makeGetVerifyDeployBuildInfo, + makeGetVerifyDeployArtifact, + makeGetBytecodeDigest, + } = require('@openzeppelin/hardhat-upgrades/dist/defender-v1/verify-deployment'); + const { makeProposeUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/defender-v1/propose-upgrade'); + + return { + proposeUpgrade: makeProposeUpgrade(this._hre), + verifyDeployment: makeVerifyDeploy(this._hre), + verifyDeploymentWithUploadedArtifact: makeVerifyDeployWithUploadedArtifact(this._hre), + getDeploymentArtifact: makeGetVerifyDeployArtifact(this._hre), + getDeploymentBuildInfo: makeGetVerifyDeployBuildInfo(this._hre), + getBytecodeDigest: makeGetBytecodeDigest(this._hre), + }; + } + + private warnOnHardhatDefender() { + if (tryRequire('@openzeppelin/hardhat-defender', true)) { + const { logWarning } = require('@openzeppelin/upgrades-core'); + logWarning('The @openzeppelin/hardhat-defender package is deprecated.', [ + 'Uninstall the @openzeppelin/hardhat-defender package.', + 'OpenZeppelin Defender integration is included as part of the Hardhat Upgrades plugin.', + ]); + } + } +} diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index d62222029..5e03661fd 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -3,15 +3,10 @@ import './type-extensions'; import { extendEnvironment, subtask, task, types } from 'hardhat/internal/core/config/config-env'; -import { - TASK_COMPILE_SOLIDITY_COMPILE, - TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, -} from 'hardhat/builtin-tasks/task-names'; +import { TASK_COMPILE_SOLIDITY_COMPILE } from 'hardhat/builtin-tasks/task-names'; -import { lazyObject } from 'hardhat/plugins'; -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { HardhatUpgrades, HardhatZksyncUpgrades, RunCompilerArgs } from './interfaces'; -import { extendCompilerOutputSelection, isFullZkSolcOutput } from './utils/utils-general'; +import { RunCompilerArgs } from './interfaces'; +import { isFullZkSolcOutput } from './utils/utils-general'; import { validate } from './core/validate'; import { TASK_DEPLOY_ZKSYNC_BEACON, @@ -20,175 +15,13 @@ import { TASK_UPGRADE_ZKSYNC_PROXY, } from './task-names'; import { deployZkSyncBeacon, deployZkSyncProxy, upgradeZkSyncBeacon, upgradeZkSyncProxy } from './task-actions'; -import { checkOpenzeppelinVersions, getUpgradableContracts } from './utils'; -import { silenceWarnings } from './log'; +import { ExtensionGenerator } from './extension-generator'; extendEnvironment((hre) => { - if (hre.network.zksync) { - hre.zkUpgrades = lazyObject(() => { - return makeZkSyncFunction(hre) as HardhatZksyncUpgrades & HardhatUpgrades; - }); - - hre.upgrades = lazyObject(() => { - return makeZkSyncFunction(hre) as HardhatZksyncUpgrades & HardhatUpgrades; - }); - - hre.defender = undefined; - - hre.config.solidity.compilers.forEach((compiler) => { - extendCompilerOutputSelection(compiler); - }); - } else { - hre.upgrades = lazyObject(() => { - return makeUpgradesFunctions(hre) as HardhatZksyncUpgrades & HardhatUpgrades; - }); - - warnOnHardhatDefender(); - - hre.defender = lazyObject(() => { - return makeDefenderFunctions(hre); - }); - - hre.zkUpgrades = undefined as any; - } + const extesionGenerator = new ExtensionGenerator(hre); + extesionGenerator.populateExtension(); }); -function warnOnHardhatDefender() { - if (tryRequire('@openzeppelin/hardhat-defender', true)) { - const { logWarning } = require('@openzeppelin/upgrades-core'); - logWarning('The @openzeppelin/hardhat-defender package is deprecated.', [ - 'Uninstall the @openzeppelin/hardhat-defender package.', - 'OpenZeppelin Defender integration is included as part of the Hardhat Upgrades plugin.', - ]); - } -} - -function tryRequire(id: string, resolveOnly?: boolean) { - try { - if (resolveOnly) { - require.resolve(id); - } else { - require(id); - } - return true; - } catch (e: any) { - // do nothing - } - return false; -} - -function makeFunctions(hre: HardhatRuntimeEnvironment, defender: boolean): HardhatUpgrades { - const { getImplementationAddressFromBeacon } = require('@openzeppelin/upgrades-core/dist/impl-address'); - const { - getAdminAddress, - getImplementationAddress, - getBeaconAddress, - } = require('@openzeppelin/upgrades-core/dist/eip-1967'); - const { makeDeployProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy'); - const { makeUpgradeProxy } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'); - const { makeValidateImplementation } = require('@openzeppelin/hardhat-upgrades/dist/validate-implementation'); - const { makeValidateUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/validate-upgrade'); - const { makeDeployImplementation } = require('@openzeppelin/hardhat-upgrades/dist/deploy-implementation'); - const { makePrepareUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'); - const { makeDeployBeacon } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon'); - const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); - const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); - const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); - /* eslint-disable @typescript-eslint/no-shadow */ - const { - makeChangeProxyAdmin, - makeTransferProxyAdminOwnership, - } = require('@openzeppelin/hardhat-upgrades/dist/admin'); - /* eslint-enable @typescript-eslint/no-shadow */ - - return { - silenceWarnings, - deployProxy: makeDeployProxy(hre, defender), - upgradeProxy: makeUpgradeProxy(hre, defender), // block on defender - validateImplementation: makeValidateImplementation(hre), - validateUpgrade: makeValidateUpgrade(hre), - deployImplementation: makeDeployImplementation(hre, defender), - prepareUpgrade: makePrepareUpgrade(hre, defender), - deployBeacon: makeDeployBeacon(hre, defender), // block on defender - deployBeaconProxy: makeDeployBeaconProxy(hre, defender), - upgradeBeacon: makeUpgradeBeacon(hre, defender), // block on defender - forceImport: makeForceImport(hre), - admin: { - changeProxyAdmin: makeChangeProxyAdmin(hre, defender), // block on defender - transferProxyAdminOwnership: makeTransferProxyAdminOwnership(hre, defender), // block on defender - }, - erc1967: { - getAdminAddress: (proxyAddress: string) => getAdminAddress(hre.network.provider, proxyAddress), - getImplementationAddress: (proxyAddress: string) => - getImplementationAddress(hre.network.provider, proxyAddress), - getBeaconAddress: (proxyAddress: string) => getBeaconAddress(hre.network.provider, proxyAddress), - }, - beacon: { - getImplementationAddress: (beaconAddress: string) => - getImplementationAddressFromBeacon(hre.network.provider, beaconAddress), - }, - }; -} - -function makeDefenderFunctions(hre: HardhatRuntimeEnvironment) { - const { makeDeployContract } = require('@openzeppelin/hardhat-upgrades/dist/deploy-contract'); - const { - makeProposeUpgradeWithApproval, - } = require('@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'); - const { - makeGetDeployApprovalProcess, - makeGetUpgradeApprovalProcess, - } = require('@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'); - - const getUpgradeApprovalProcess = makeGetUpgradeApprovalProcess(hre); - - return { - ...makeFunctions(hre, true), - deployContract: makeDeployContract(hre, true), - proposeUpgradeWithApproval: makeProposeUpgradeWithApproval(hre, true), - getDeployApprovalProcess: makeGetDeployApprovalProcess(hre), - getUpgradeApprovalProcess, - getDefaultApprovalProcess: getUpgradeApprovalProcess, // deprecated, is an alias for getUpgradeApprovalProcess - }; -} - -function makeUpgradesFunctions(hre: HardhatRuntimeEnvironment): HardhatUpgrades { - return makeFunctions(hre, false); -} - -function makeZkSyncFunction(hre: HardhatRuntimeEnvironment): HardhatZksyncUpgrades { - const { makeDeployProxy } = require('./proxy-deployment/deploy-proxy'); - const { makeUpgradeProxy } = require('./proxy-upgrade/upgrade-proxy'); - const { makeValidateImplementation } = require('./validations/validate-implementation'); - const { makeDeployBeacon } = require('./proxy-deployment/deploy-beacon'); - const { makeDeployBeaconProxy } = require('./proxy-deployment/deploy-beacon-proxy'); - const { makeUpgradeBeacon } = require('./proxy-upgrade/upgrade-beacon'); - const { makeDeployProxyAdmin } = require('./proxy-deployment/deploy-proxy-admin'); - const { makeEstimateGasProxy } = require('./gas-estimation/estimate-gas-proxy'); - const { makeEstimateGasBeacon } = require('./gas-estimation/estimate-gas-beacon'); - const { makeEstimateGasBeaconProxy } = require('./gas-estimation/estimate-gas-beacon-proxy'); - const { makeGetInstanceFunction, makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); - return { - deployProxy: checkOpenzeppelinVersions(makeDeployProxy(hre)), - upgradeProxy: checkOpenzeppelinVersions(makeUpgradeProxy(hre)), - validateImplementation: checkOpenzeppelinVersions(makeValidateImplementation(hre)), - deployBeacon: checkOpenzeppelinVersions(makeDeployBeacon(hre)), - deployBeaconProxy: checkOpenzeppelinVersions(makeDeployBeaconProxy(hre)), - upgradeBeacon: checkOpenzeppelinVersions(makeUpgradeBeacon(hre)), - deployProxyAdmin: checkOpenzeppelinVersions(makeDeployProxyAdmin(hre)), - admin: { - getInstance: checkOpenzeppelinVersions(makeGetInstanceFunction(hre)), - changeProxyAdmin: checkOpenzeppelinVersions(makeChangeProxyAdmin(hre)), - transferProxyAdminOwnership: checkOpenzeppelinVersions(makeTransferProxyAdminOwnership(hre)), - }, - estimation: { - estimateGasProxy: checkOpenzeppelinVersions(makeEstimateGasProxy(hre)), - estimateGasBeacon: checkOpenzeppelinVersions(makeEstimateGasBeacon(hre)), - estimateGasBeaconProxy: checkOpenzeppelinVersions(makeEstimateGasBeaconProxy(hre)), - }, - }; -} - task(TASK_DEPLOY_ZKSYNC_BEACON, 'Runs the beaccon deploy for ZKsync network') .addParam('contractName', 'A contract name or a FQN', '') .addOptionalVariadicPositionalParam( @@ -262,22 +95,6 @@ subtask(TASK_COMPILE_SOLIDITY_COMPILE, async (args: RunCompilerArgs, hre, runSup return { output, solcBuild }; }); -subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, async (args: RunCompilerArgs, _, runSuper) => { - const sourceNames = await runSuper(); - - const upgradableContracts = getUpgradableContracts(); - return [ - ...sourceNames, - ...[ - upgradableContracts.ProxyAdmin, - upgradableContracts.TransparentUpgradeableProxy, - upgradableContracts.BeaconProxy, - upgradableContracts.UpgradeableBeacon, - upgradableContracts.ERC1967Proxy, - ], - ]; -}); - subtask('verify:verify').setAction(async (args, hre, runSuper) => { const { verify } = await import('./verify/verify-proxy'); return await verify(args, hre, runSuper); diff --git a/packages/hardhat-zksync-upgradable/src/interfaces.ts b/packages/hardhat-zksync-upgradable/src/interfaces.ts index bf1cfe2af..9df5f5eff 100644 --- a/packages/hardhat-zksync-upgradable/src/interfaces.ts +++ b/packages/hardhat-zksync-upgradable/src/interfaces.ts @@ -1,30 +1,44 @@ -import { SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; +import { silenceWarnings, SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; import * as zk from 'zksync-ethers'; -import { DeployFunction as _DeployFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy'; -import { PrepareUpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'; -import { UpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'; -import { DeployBeaconFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; -import { DeployBeaconProxyFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; -import { UpgradeBeaconFunction } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; -import { ForceImportFunction } from '@openzeppelin/hardhat-upgrades/dist/force-import'; +import { DeployFunction as DeployFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy'; +import { PrepareUpgradeFunction as PrepareUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'; +import { UpgradeFunction as UpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'; +import { DeployBeaconFunction as DeployBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; +import { DeployBeaconProxyFunction as DeployBeaconProxyFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; +import { UpgradeBeaconFunction as UpgradeBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; +import { ForceImportFunction as ForceImportFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/force-import'; import { - ChangeAdminFunction as _ChangeAdminFunction, - TransferProxyAdminOwnershipFunction as _TransferProxyAdminOwnershipFunction, + ChangeAdminFunction as ChangeAdminFunctionOZ, + TransferProxyAdminOwnershipFunction as TransferProxyAdminOwnershipFunctionOZ, + GetInstanceFunction as GetInstanceFunctionOZ, } from '@openzeppelin/hardhat-upgrades/dist/admin'; -import { ValidateImplementationFunction as _ValidateImplementationFunction } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; -import { ValidateUpgradeFunction } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; -import { DeployImplementationFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-implementation'; -import { DeployContractFunction } from '@openzeppelin/hardhat-upgrades/dist/deploy-contract'; -// import { ProposeUpgradeWithApprovalFunction } from '@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'; +import { ValidateImplementationFunction as ValidateImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; +import { ValidateUpgradeFunction as ValidateUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; +import { DeployImplementationFunction as DeployImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-implementation'; +import { DeployContractFunction as DeployContractFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-contract'; import { - GetDeployApprovalProcessFunction, - GetUpgradeApprovalProcessFunction, + GetDeployApprovalProcessFunction as GetDeployApprovalProcessFunctionOZ, + GetUpgradeApprovalProcessFunction as GetUpgradeApprovalProcessFunctionOZ, } from '@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'; + +// import type { ProposeUpgradeFunction as ProposeUpgradeFunctionOZ} from '@openzeppelin/hardhat-upgrades/dist/defender-v1/propose-upgrade'; +// import type { +// VerifyDeployFunction as VerifyDeployFunctionOZ, +// VerifyDeployWithUploadedArtifactFunction as VerifyDeployWithUploadedArtifactFunctionOZ, +// GetVerifyDeployArtifactFunction as GetVerifyDeployArtifactFunctionOZ, +// GetVerifyDeployBuildInfoFunction as GetVerifyDeployBuildInfoFunctionOZ, +// GetBytecodeDigestFunction as GetBytecodeDigestFunctionOZ, +// } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/verify-deployment'; + import { UpgradeProxyArtifact, UpgradeProxyFactory } from './proxy-upgrade/upgrade-proxy'; import { UpgradeBeaconArtifact, UpgradeBeaconFactory } from './proxy-upgrade/upgrade-beacon'; -import { DeployFunctionArtifact, DeployFunctionFactory } from './proxy-deployment/deploy-proxy'; +import { + DeployFunctionArtifact, + DeployFunctionFactory, + DeployFunctionFactoryNoArgs, +} from './proxy-deployment/deploy-proxy'; import { DeployBeaconArtifact, DeployBeaconFactory } from './proxy-deployment/deploy-beacon'; import { DeployBeaconProxyArtifact, DeployBeaconProxyFactory } from './proxy-deployment/deploy-beacon-proxy'; import { EstimateProxyGasFunction } from './gas-estimation/estimate-gas-proxy'; @@ -33,22 +47,31 @@ import { ChangeAdminFunction, GetInstanceFunction, TransferProxyAdminOwnershipFu import { ValidateImplementationOptions } from './utils/options'; import { DeployAdminFunction } from './proxy-deployment/deploy-proxy-admin'; -export interface HardhatUpgrades { - deployProxy: _DeployFunction; - upgradeProxy: UpgradeFunction; - validateImplementation: _ValidateImplementationFunction; - validateUpgrade: ValidateUpgradeFunction; - deployImplementation: DeployImplementationFunction; - prepareUpgrade: PrepareUpgradeFunction; - deployBeacon: DeployBeaconFunction; - deployBeaconProxy: DeployBeaconProxyFunction; - upgradeBeacon: UpgradeBeaconFunction; - forceImport: ForceImportFunction; - // silenceWarnings: typeof silenceWarnings; - silenceWarnings: any; +export type UndefinedFunctionType = (...args: any[]) => any; + +export function makeUndefinedFunction(): UndefinedFunctionType { + return (..._: any[]) => { + throw new Error('This function is not implemented'); + }; +} + +export interface HardhatUpgradesOZ { + deployProxy: DeployFunctionOZ; + upgradeProxy: UpgradeFunctionOZ; + validateImplementation: ValidateImplementationFunctionOZ; + validateUpgrade: ValidateUpgradeFunctionOZ; + deployImplementation: DeployImplementationFunctionOZ; + prepareUpgrade: PrepareUpgradeFunctionOZ; + deployBeacon: DeployBeaconFunctionOZ; + deployBeaconProxy: DeployBeaconProxyFunctionOZ; + upgradeBeacon: UpgradeBeaconFunctionOZ; + forceImport: ForceImportFunctionOZ; + silenceWarnings: typeof silenceWarnings; admin: { - changeProxyAdmin: _ChangeAdminFunction; - transferProxyAdminOwnership: _TransferProxyAdminOwnershipFunction; + // property from zksync + getInstance: GetInstanceFunctionOZ; + changeProxyAdmin: ChangeAdminFunctionOZ; + transferProxyAdminOwnership: TransferProxyAdminOwnershipFunctionOZ; }; erc1967: { getAdminAddress: (proxyAdress: string) => Promise; @@ -58,18 +81,34 @@ export interface HardhatUpgrades { beacon: { getImplementationAddress: (beaconAddress: string) => Promise; }; + // Properties from zksync + deployProxyAdmin: UndefinedFunctionType; + estimation: { + estimateGasProxy: UndefinedFunctionType; + estimateGasBeacon: UndefinedFunctionType; + estimateGasBeaconProxy: UndefinedFunctionType; + }; } -export type DefenderHardhatUpgrades = { - deployContract: DeployContractFunction; +// export type DefenderV1HardhatUpgradesOZ = { +// proposeUpgrade: ProposeUpgradeFunctionOZ; +// verifyDeployment: VerifyDeployFunctionOZ; +// verifyDeploymentWithUploadedArtifact: VerifyDeployWithUploadedArtifactFunctionOZ; +// getDeploymentArtifact: GetVerifyDeployArtifactFunctionOZ; +// getDeploymentBuildInfo: GetVerifyDeployBuildInfoFunctionOZ; +// getBytecodeDigest: GetBytecodeDigestFunctionOZ; +// } + +export type DefenderHardhatUpgradesOZ = { + deployContract: DeployContractFunctionOZ; proposeUpgradeWithApproval: any; - getDeployApprovalProcess: GetDeployApprovalProcessFunction; - getUpgradeApprovalProcess: GetUpgradeApprovalProcessFunction; + getDeployApprovalProcess: GetDeployApprovalProcessFunctionOZ; + getUpgradeApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; /** * @deprecated Use `getUpgradeApprovalProcess` instead. */ - getDefaultApprovalProcess: GetUpgradeApprovalProcessFunction; -} & HardhatUpgrades; + getDefaultApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; +} & HardhatUpgradesOZ; export type ValidateImplementationFunction = ( ImplFactory: zk.ContractFactory, @@ -77,7 +116,7 @@ export type ValidateImplementationFunction = ( ) => Promise; export interface HardhatZksyncUpgrades { - deployProxy: DeployFunctionArtifact & DeployFunctionFactory; + deployProxy: DeployFunctionArtifact & DeployFunctionFactory & DeployFunctionFactoryNoArgs; upgradeProxy: UpgradeProxyFactory & UpgradeProxyArtifact; validateImplementation: ValidateImplementationFunction; deployBeacon: DeployBeaconArtifact & DeployBeaconFactory; @@ -94,6 +133,20 @@ export interface HardhatZksyncUpgrades { estimateGasBeacon: EstimateProxyGasFunction; estimateGasBeaconProxy: EstimateBeaconGasFunction; }; + // Properties from oz-upgrades + forceImport: UndefinedFunctionType; + silenceWarnings: UndefinedFunctionType; + validateUpgrade: UndefinedFunctionType; + deployImplementation: UndefinedFunctionType; + prepareUpgrade: UndefinedFunctionType; + beacon: { + getImplementationAddress: UndefinedFunctionType; + }; + erc1967: { + getAdminAddress: UndefinedFunctionType; + getImplementationAddress: UndefinedFunctionType; + getBeaconAddress: UndefinedFunctionType; + }; } export interface RunCompilerArgs { diff --git a/packages/hardhat-zksync-upgradable/src/plugin.ts b/packages/hardhat-zksync-upgradable/src/plugin.ts index fb0ff54ce..1ab17f1b3 100644 --- a/packages/hardhat-zksync-upgradable/src/plugin.ts +++ b/packages/hardhat-zksync-upgradable/src/plugin.ts @@ -37,7 +37,7 @@ export async function deployBeacon( const contract = await deployer.loadArtifact(taskArgs.contractName); const factory = new ContractFactory(contract.abi, contract.bytecode, wallet); - const beacon = await hre.upgrades.deployBeacon(factory, [], { + const beacon = await hre.upgrades.deployBeacon(factory, { deploymentType: taskArgs.deploymentTypeImpl, salt: taskArgs.saltImpl, }); diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts index a47577df2..baa1e3499 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts @@ -43,7 +43,7 @@ export function makeDeployBeaconProxy( return async function ( ...args: Parameters ): Promise { - const target = args[0]; + const target = args[1]; if (target instanceof zk.ContractFactory) { return deployBeaconProxyFactory(hre, ...(args as Parameters)); } else { diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts index f01bab07d..efa49f61b 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts @@ -18,7 +18,6 @@ import { deploy, DeployTransaction } from './deploy'; export type DeployBeaconFactory = ( factory: zk.ContractFactory, - args?: unknown[], opts?: DeployBeaconOptions, quiet?: boolean, ) => Promise; @@ -45,15 +44,9 @@ export function makeDeployBeacon(hre: HardhatRuntimeEnvironment): DeployBeaconFa export async function deployBeaconFactory( hre: HardhatRuntimeEnvironment, factory: zk.ContractFactory, - args?: unknown[], opts?: DeployBeaconOptions, quiet?: boolean, ): Promise { - if (!Array.isArray(args)) { - opts = args; - args = []; - } - const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; if (!wallet) { throw new ZkSyncUpgradablePluginError('Wallet is required for deployment'); @@ -63,7 +56,7 @@ export async function deployBeaconFactory( opts.provider = wallet?.provider; opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); - return deployProxyBeacon(hre, factory, wallet, args, opts, quiet); + return deployProxyBeacon(hre, factory, wallet, undefined, opts, quiet); } export async function deployBeaconArtifact( diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts index 5fc094369..fdfdd1498 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts @@ -23,6 +23,12 @@ export type DeployFunctionFactory = ( quiet?: boolean, ) => Promise; +export type DeployFunctionFactoryNoArgs = ( + factory: zk.ContractFactory, + opts?: DeployProxyOptions, + quiet?: boolean, +) => Promise; + export type DeployFunctionArtifact = ( wallet: zk.Wallet, artifact: ZkSyncArtifact, @@ -31,10 +37,18 @@ export type DeployFunctionArtifact = ( quiet?: boolean, ) => Promise; -export function makeDeployProxy(hre: HardhatRuntimeEnvironment): DeployFunctionFactory | DeployFunctionArtifact { - return async function (...args: Parameters): Promise { +export function makeDeployProxy( + hre: HardhatRuntimeEnvironment, +): DeployFunctionFactory | DeployFunctionFactoryNoArgs | DeployFunctionArtifact { + return async function ( + ...args: Parameters + ): Promise { const target = args[0]; if (target instanceof zk.ContractFactory) { + const targetArgs = args[1]; + if (targetArgs && 'initializer' in targetArgs) { + return await deployProxyFactoryNoArgs(hre, ...(args as Parameters)); + } return await deployProxyFactory(hre, ...(args as Parameters)); } else { return deployProxyArtifact(hre, ...(args as Parameters)); @@ -65,6 +79,23 @@ export async function deployProxyFactory( return deployProxy(hre, factory, wallet, args, opts, quiet); } +export async function deployProxyFactoryNoArgs( + hre: HardhatRuntimeEnvironment, + factory: zk.ContractFactory, + opts?: DeployProxyOptions, + quiet?: boolean, +): Promise { + const wallet = factory.runner && 'getAddress' in factory.runner ? (factory.runner as zk.Wallet) : undefined; + if (!wallet) { + throw new ZkSyncUpgradablePluginError('Wallet is required for deployment'); + } + opts = opts || {}; + opts.provider = wallet?.provider; + opts.factoryDeps = await extractFactoryDeps(hre, await getArtifactFromBytecode(hre, factory.bytecode)); + + return deployProxy(hre, factory, wallet, undefined, opts, quiet); +} + export async function deployProxyArtifact( hre: HardhatRuntimeEnvironment, wallet: zk.Wallet, @@ -94,7 +125,6 @@ async function deployProxy( } const manifest = await Manifest.forNetwork(wallet.provider); - const { impl, kind } = await deployProxyImpl(hre, factory, opts); if (!quiet) { console.info(chalk.green(`Implementation contract was deployed to ${impl}`)); diff --git a/packages/hardhat-zksync-upgradable/src/type-extensions.ts b/packages/hardhat-zksync-upgradable/src/type-extensions.ts index 10f44a629..dbad8cb7b 100644 --- a/packages/hardhat-zksync-upgradable/src/type-extensions.ts +++ b/packages/hardhat-zksync-upgradable/src/type-extensions.ts @@ -1,10 +1,10 @@ import 'hardhat/types/runtime'; -import { DefenderHardhatUpgrades, HardhatUpgrades, HardhatZksyncUpgrades } from './interfaces'; +import { DefenderHardhatUpgradesOZ, HardhatUpgradesOZ, HardhatZksyncUpgrades } from './interfaces'; declare module 'hardhat/types/runtime' { export interface HardhatRuntimeEnvironment { zkUpgrades: HardhatZksyncUpgrades; - upgrades: HardhatZksyncUpgrades & HardhatUpgrades; - defender: DefenderHardhatUpgrades | undefined; + upgrades: HardhatZksyncUpgrades & HardhatUpgradesOZ; + defender: DefenderHardhatUpgradesOZ; } } diff --git a/packages/hardhat-zksync-upgradable/src/utils.ts b/packages/hardhat-zksync-upgradable/src/utils.ts index 204cc48db..33a9e102c 100644 --- a/packages/hardhat-zksync-upgradable/src/utils.ts +++ b/packages/hardhat-zksync-upgradable/src/utils.ts @@ -19,8 +19,11 @@ export async function getWallet(hre: HardhatRuntimeEnvironment, privateKeyOrInde return wallet; } -export function checkOpenzeppelinVersions(wrappedFunction: (...args: any) => T): (...args: any) => T { - return function (...args: any): T { +export function wrapMakeFunction( + hre: HardhatRuntimeEnvironment, + wrappedFunction: (...args: any) => T, +): (...args: any) => Promise { + return async function (...args: any): Promise { try { if (!isOpenzeppelinContractsVersionValid()) { throw new Error(OZ_CONTRACTS_VERISION_INCOMPATIBLE_ERROR); @@ -28,6 +31,18 @@ export function checkOpenzeppelinVersions(wrappedFunction: (...args: any) => } catch (e: any) { console.warn(chalk.yellow(e.message)); } + + const upgradableContracts = getUpgradableContracts(); + hre.config.zksolc.settings.overrideContractsToCompile = [ + upgradableContracts.ProxyAdmin, + upgradableContracts.TransparentUpgradeableProxy, + upgradableContracts.BeaconProxy, + upgradableContracts.UpgradeableBeacon, + upgradableContracts.ERC1967Proxy, + ]; + await hre.run('compile', { quiet: true }); + hre.config.zksolc.settings.overrideContractsToCompile = undefined; + return wrappedFunction(...args); }; } @@ -52,3 +67,17 @@ export function getUpgradableContracts() { return UPGRADEABLE_CONTRACTS_FROM_ALIAS; } + +export function tryRequire(id: string, resolveOnly?: boolean) { + try { + if (resolveOnly) { + require.resolve(id); + } else { + require(id); + } + return true; + } catch (e: any) { + // do nothing + } + return false; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 883f0ca93..39ff24c67 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -450,8 +450,8 @@ importers: specifier: ^4.9.2 version: 4.9.6 '@openzeppelin/hardhat-upgrades': - specifier: ^3.2.1 - version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + specifier: ^2.5.1 + version: 2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) chalk: specifier: ^4.1.2 version: 4.1.2 @@ -1337,8 +1337,8 @@ importers: specifier: npm:@openzeppelin/contracts@^4.9.2 version: '@openzeppelin/contracts@4.9.6' '@openzeppelin/hardhat-upgrades': - specifier: ^3.2.1 - version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + specifier: ~2.5.1 + version: 2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@openzeppelin/upgrades-core': specifier: ^1.31.3 version: 1.33.1 @@ -1842,6 +1842,9 @@ packages: '@ethersproject/base64@5.7.0': resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==, tarball: https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz} + '@ethersproject/basex@5.7.0': + resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==, tarball: https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz} + '@ethersproject/bignumber@5.7.0': resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==, tarball: https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz} @@ -1851,9 +1854,18 @@ packages: '@ethersproject/constants@5.7.0': resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==, tarball: https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz} + '@ethersproject/contracts@5.7.0': + resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==, tarball: https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz} + '@ethersproject/hash@5.7.0': resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==, tarball: https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz} + '@ethersproject/hdnode@5.7.0': + resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==, tarball: https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz} + + '@ethersproject/json-wallets@5.7.0': + resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==, tarball: https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz} + '@ethersproject/keccak256@5.7.0': resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==, tarball: https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz} @@ -1863,24 +1875,48 @@ packages: '@ethersproject/networks@5.7.1': resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==, tarball: https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz} + '@ethersproject/pbkdf2@5.7.0': + resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==, tarball: https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz} + '@ethersproject/properties@5.7.0': resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==, tarball: https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz} + '@ethersproject/providers@5.7.2': + resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==, tarball: https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz} + + '@ethersproject/random@5.7.0': + resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==, tarball: https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz} + '@ethersproject/rlp@5.7.0': resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==, tarball: https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz} + '@ethersproject/sha2@5.7.0': + resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==, tarball: https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz} + '@ethersproject/signing-key@5.7.0': resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==, tarball: https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz} + '@ethersproject/solidity@5.7.0': + resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==, tarball: https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz} + '@ethersproject/strings@5.7.0': resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==, tarball: https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz} '@ethersproject/transactions@5.7.0': resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==, tarball: https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz} + '@ethersproject/units@5.7.0': + resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==, tarball: https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz} + + '@ethersproject/wallet@5.7.0': + resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==, tarball: https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz} + '@ethersproject/web@5.7.1': resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==, tarball: https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz} + '@ethersproject/wordlists@5.7.0': + resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==, tarball: https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz} + '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==, tarball: https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz} engines: {node: '>=14'} @@ -2163,21 +2199,26 @@ packages: '@openzeppelin/contracts@4.9.6': resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz} + '@openzeppelin/defender-admin-client@1.54.6': + resolution: {integrity: sha512-P4lxJDySrekWNuPa7FeyW/UmuxnuIXIAGYr5gZnmnMHRsYNaw+XfgkiCDfoGtjEyJbXYxXttYF6iAZhWQPdf1g==, tarball: https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.6.tgz} + deprecated: This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead. + + '@openzeppelin/defender-base-client@1.54.6': + resolution: {integrity: sha512-PTef+rMxkM5VQ7sLwLKSjp2DBakYQd661ZJiSRywx+q/nIpm3B/HYGcz5wPZCA5O/QcEP6TatXXDoeMwimbcnw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.6.tgz} + deprecated: This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead. + '@openzeppelin/defender-sdk-base-client@1.14.3': resolution: {integrity: sha512-4yG9E8N1c/ZP2jNR+Ah19wi7SBKpauAV/VcYcm7rg1dltDbzbH/oZnnXJlymT7IfjTPXkKHW8TPsaqz3EjS7tA==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.3.tgz} '@openzeppelin/defender-sdk-deploy-client@1.14.3': resolution: {integrity: sha512-51WIZJz251lndK7uQU4gBE0gBX+2ZNTgf+hemtJUEPCpHtkooBRFFMID3EPGMKXVqf872pU8K3Huu9PyYQu6bw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.3.tgz} - '@openzeppelin/defender-sdk-network-client@1.14.3': - resolution: {integrity: sha512-qrJLs2ubKSwrhP0x4V2QOPhlc1q8TYnkAcvjvk34VXMS8lhY1cpXSGoxnTw3Mi+eCSE1xOzKWISLi1UAOQOJIw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.14.3.tgz} - - '@openzeppelin/hardhat-upgrades@3.2.1': - resolution: {integrity: sha512-Zy5M3QhkzwGdpzQmk+xbWdYOGJWjoTvwbBKYLhctu9B91DoprlhDRaZUwCtunwTdynkTDGdVfGr0kIkvycyKjw==, tarball: https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.2.1.tgz} + '@openzeppelin/hardhat-upgrades@2.5.1': + resolution: {integrity: sha512-wRwq9f2PqlfIdNGFApsqRpqptqy98exSFp8SESb6Brgw4L07sExySInNJhscM/tWVSnR1Qnuws9Ck6Fs5zIxvg==, tarball: https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.5.1.tgz} hasBin: true peerDependencies: '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 + '@nomicfoundation/hardhat-verify': ^1.1.0 ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: @@ -2526,6 +2567,9 @@ packages: resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==, tarball: https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz} engines: {node: '>=0.3.0'} + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==, tarball: https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz} + aes-js@4.0.0-beta.5: resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==, tarball: https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz} @@ -2680,6 +2724,9 @@ packages: bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==, tarball: https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz} + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==, tarball: https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==, tarball: https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz} engines: {node: '>=4'} @@ -3336,6 +3383,9 @@ packages: resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==, tarball: https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz} engines: {node: '>=10.0.0'} + ethers@5.7.2: + resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==, tarball: https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz} + ethers@6.12.2: resolution: {integrity: sha512-MNfR2kzZyNF8bRNDSmjM+rT1+yqCgYNqfrXyNnpiNId2MQPiAOOr/7lrgdrdwoBxzKPSnSYZaGb5lcNyvzhuvA==, tarball: https://registry.npmjs.org/ethers/-/ethers-6.12.2.tgz} engines: {node: '>=14.0.0'} @@ -5052,6 +5102,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, tarball: https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz} + ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==, tarball: https://registry.npmjs.org/ws/-/ws-7.4.6.tgz} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==, tarball: https://registry.npmjs.org/ws/-/ws-7.5.9.tgz} engines: {node: '>=8.3.0'} @@ -5428,6 +5490,11 @@ snapshots: dependencies: '@ethersproject/bytes': 5.7.0 + '@ethersproject/basex@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/bignumber@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5442,6 +5509,19 @@ snapshots: dependencies: '@ethersproject/bignumber': 5.7.0 + '@ethersproject/contracts@5.7.0': + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/hash@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 @@ -5454,6 +5534,37 @@ snapshots: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 + '@ethersproject/hdnode@5.7.0': + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 + + '@ethersproject/json-wallets@5.7.0': + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + '@ethersproject/keccak256@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5465,15 +5576,57 @@ snapshots: dependencies: '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/properties@5.7.0': dependencies: '@ethersproject/logger': 5.7.0 + '@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + bech32: 1.1.4 + ws: 7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ethersproject/random@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/rlp@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 + '@ethersproject/sha2@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + hash.js: 1.1.7 + '@ethersproject/signing-key@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5483,6 +5636,15 @@ snapshots: elliptic: 6.5.4 hash.js: 1.1.7 + '@ethersproject/solidity@5.7.0': + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/strings@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5501,6 +5663,30 @@ snapshots: '@ethersproject/rlp': 5.7.0 '@ethersproject/signing-key': 5.7.0 + '@ethersproject/units@5.7.0': + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + + '@ethersproject/wallet@5.7.0': + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/json-wallets': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 + '@ethersproject/web@5.7.1': dependencies: '@ethersproject/base64': 5.7.0 @@ -5509,6 +5695,14 @@ snapshots: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 + '@ethersproject/wordlists@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@fastify/busboy@2.1.1': {} '@humanwhocodes/config-array@0.11.14': @@ -5785,23 +5979,38 @@ snapshots: '@openzeppelin/contracts@4.9.6': {} - '@openzeppelin/defender-sdk-base-client@1.14.3': + '@openzeppelin/defender-admin-client@1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10)': dependencies: - amazon-cognito-identity-js: 6.3.12 - async-retry: 1.3.3 + '@openzeppelin/defender-base-client': 1.54.6(debug@4.3.5) + axios: 1.7.2(debug@4.3.5) + ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + lodash: 4.17.21 + node-fetch: 2.7.0 transitivePeerDependencies: + - bufferutil + - debug - encoding + - utf-8-validate - '@openzeppelin/defender-sdk-deploy-client@1.14.3(debug@4.3.5)': + '@openzeppelin/defender-base-client@1.54.6(debug@4.3.5)': dependencies: - '@openzeppelin/defender-sdk-base-client': 1.14.3 + amazon-cognito-identity-js: 6.3.12 + async-retry: 1.3.3 axios: 1.7.2(debug@4.3.5) lodash: 4.17.21 + node-fetch: 2.7.0 transitivePeerDependencies: - debug - encoding - '@openzeppelin/defender-sdk-network-client@1.14.3(debug@4.3.5)': + '@openzeppelin/defender-sdk-base-client@1.14.3': + dependencies: + amazon-cognito-identity-js: 6.3.12 + async-retry: 1.3.3 + transitivePeerDependencies: + - encoding + + '@openzeppelin/defender-sdk-deploy-client@1.14.3(debug@4.3.5)': dependencies: '@openzeppelin/defender-sdk-base-client': 1.14.3 axios: 1.7.2(debug@4.3.5) @@ -5810,12 +6019,13 @@ snapshots: - debug - encoding - '@openzeppelin/hardhat-upgrades@3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@openzeppelin/hardhat-upgrades@2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': dependencies: '@nomicfoundation/hardhat-ethers': 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@openzeppelin/defender-admin-client': 1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10) + '@openzeppelin/defender-base-client': 1.54.6(debug@4.3.5) '@openzeppelin/defender-sdk-base-client': 1.14.3 '@openzeppelin/defender-sdk-deploy-client': 1.14.3(debug@4.3.5) - '@openzeppelin/defender-sdk-network-client': 1.14.3(debug@4.3.5) '@openzeppelin/upgrades-core': 1.35.0 chalk: 4.1.2 debug: 4.3.5 @@ -5823,12 +6033,12 @@ snapshots: ethers: 6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat: 2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) proper-lockfile: 4.1.2 - undici: 6.18.2 - optionalDependencies: - '@nomicfoundation/hardhat-verify': 2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + undici: 5.28.4 transitivePeerDependencies: + - bufferutil - encoding - supports-color + - utf-8-validate '@openzeppelin/upgrades-core@1.33.1': dependencies: @@ -6269,6 +6479,8 @@ snapshots: adm-zip@0.4.16: {} + aes-js@3.0.0: {} + aes-js@4.0.0-beta.5: {} agent-base@6.0.2: @@ -6458,6 +6670,8 @@ snapshots: dependencies: tweetnacl: 0.14.5 + bech32@1.1.4: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -7362,6 +7576,42 @@ snapshots: ethereum-cryptography: 0.1.3 rlp: 2.2.7 + ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/json-wallets': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@ethersproject/random': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/solidity': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/units': 5.7.0 + '@ethersproject/wallet': 5.7.0 + '@ethersproject/web': 5.7.1 + '@ethersproject/wordlists': 5.7.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: '@adraffy/ens-normalize': 1.10.1 @@ -9214,6 +9464,11 @@ snapshots: wrappy@1.0.2: {} + ws@7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10): + optionalDependencies: + bufferutil: 4.0.8 + utf-8-validate: 5.0.10 + ws@7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10): optionalDependencies: bufferutil: 4.0.8 From 055ea65bd09398d91436e0690c93807171b5ccfe Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 14 Aug 2024 15:18:12 +0200 Subject: [PATCH 05/20] fix: add defender v1 and redesign code --- .../hardhat-zksync-upgradable/package.json | 2 + .../src/extension-generator.ts | 154 +----------------- .../src/generator.ts | 22 +++ .../hardhat-zksync-upgradable/src/index.ts | 3 +- .../src/interfaces.ts | 96 +---------- .../defender-v1/propose-upgrade.ts | 103 ++++++++++++ .../defender-v1/verify-deployment.ts | 100 ++++++++++++ .../extension-generator.ts | 133 +++++++++++++++ .../interfaces.ts | 89 ++++++++++ .../src/type-extensions.ts | 20 ++- .../hardhat-zksync-upgradable/src/utils.ts | 8 + .../test/constants.ts | 3 +- .../contracts/BoxWithStorageGapV2.sol | 4 +- .../contracts/BoxWithStorageGapV2Invalid.sol | 4 +- .../hardhat-zksync-upgradable/test/tests.ts | 2 +- pnpm-lock.yaml | 6 + 16 files changed, 498 insertions(+), 251 deletions(-) create mode 100644 packages/hardhat-zksync-upgradable/src/generator.ts create mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts create mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts create mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts create mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts diff --git a/packages/hardhat-zksync-upgradable/package.json b/packages/hardhat-zksync-upgradable/package.json index 8e411b4e0..79ca7be1e 100644 --- a/packages/hardhat-zksync-upgradable/package.json +++ b/packages/hardhat-zksync-upgradable/package.json @@ -38,6 +38,8 @@ "@openzeppelin/contracts-hardhat-zksync-upgradable": "npm:@openzeppelin/contracts@^4.9.2", "@openzeppelin/hardhat-upgrades": "~2.5.1", "@openzeppelin/upgrades-core": "^1.31.3", + "@nomicfoundation/hardhat-ethers": "^3.0.6", + "@openzeppelin/defender-admin-client": "^1.52.0", "chalk": "^4.1.2", "compare-versions": "^6.1.0", "ethereumjs-util": "^7.1.5", diff --git a/packages/hardhat-zksync-upgradable/src/extension-generator.ts b/packages/hardhat-zksync-upgradable/src/extension-generator.ts index ad94fb3a5..19a1097e5 100644 --- a/packages/hardhat-zksync-upgradable/src/extension-generator.ts +++ b/packages/hardhat-zksync-upgradable/src/extension-generator.ts @@ -1,28 +1,11 @@ import { lazyObject } from 'hardhat/plugins'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { tryRequire, wrapMakeFunction } from './utils'; -import { HardhatUpgradesOZ, HardhatZksyncUpgrades, makeUndefinedFunction } from './interfaces'; +import { makeUndefinedFunction, wrapMakeFunction } from './utils'; +import { HardhatZksyncUpgrades } from './interfaces'; +import { HardhatUpgradesOZ } from './openzeppelin-hardhat-upgrades/interfaces'; +import { Generator } from './generator'; -export class ExtensionGenerator { - constructor(private _hre: HardhatRuntimeEnvironment) {} - - public populateExtension(): void { - if (this._hre.network.zksync) { - const zkSyncGenerator = new ZkSyncGenerator(this._hre); - zkSyncGenerator.populateExtension(); - return; - } - - const ethersGenerators = new EthersGenerator(this._hre); - ethersGenerators.populateExtension(); - } -} - -interface Generator { - populateExtension(): void; -} - -class ZkSyncGenerator implements Generator { +export class ZkSyncGenerator implements Generator { constructor(private _hre: HardhatRuntimeEnvironment) {} public populateExtension(): void { @@ -77,130 +60,3 @@ class ZkSyncGenerator implements Generator { }; } } - -class EthersGenerator implements Generator { - constructor(private _hre: HardhatRuntimeEnvironment) {} - - public populateExtension(): void { - this._hre.upgrades = lazyObject(() => this.makeFunctions(false) as HardhatUpgradesOZ & HardhatZksyncUpgrades); - this.warnOnHardhatDefender(); - this._hre.defender = lazyObject(() => this.makeDefenderFunctions()); - } - - private makeFunctions(defender: boolean): HardhatUpgradesOZ { - const { - getImplementationAddressFromBeacon, - silenceWarnings, - } = require('@openzeppelin/upgrades-core/dist/impl-address'); - const { - getAdminAddress, - getImplementationAddress, - getBeaconAddress, - } = require('@openzeppelin/upgrades-core/dist/eip-1967'); - const { makeDeployProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy'); - const { makeUpgradeProxy } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'); - const { makeValidateImplementation } = require('@openzeppelin/hardhat-upgrades/dist/validate-implementation'); - const { makeValidateUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/validate-upgrade'); - const { makeDeployImplementation } = require('@openzeppelin/hardhat-upgrades/dist/deploy-implementation'); - const { makePrepareUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'); - const { makeDeployBeacon } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon'); - const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); - const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); - const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); - const { makeDeployProxyAdmin } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'); - const { - makeChangeProxyAdmin, - makeTransferProxyAdminOwnership, - makeGetInstanceFunction, - } = require('@openzeppelin/hardhat-upgrades/dist/admin'); - - return { - silenceWarnings, - deployProxy: makeDeployProxy(this._hre, defender), - upgradeProxy: makeUpgradeProxy(this._hre, defender), // block on defender - validateImplementation: makeValidateImplementation(this._hre), - validateUpgrade: makeValidateUpgrade(this._hre), - deployImplementation: makeDeployImplementation(this._hre, defender), - prepareUpgrade: makePrepareUpgrade(this._hre, defender), - deployBeacon: makeDeployBeacon(this._hre, defender), // block on defender - deployBeaconProxy: makeDeployBeaconProxy(this._hre, defender), - deployProxyAdmin: makeDeployProxyAdmin(this._hre, defender), - upgradeBeacon: makeUpgradeBeacon(this._hre, defender), // block on defender - forceImport: makeForceImport(this._hre), - admin: { - getInstance: makeGetInstanceFunction(this._hre, defender), // block on defender - changeProxyAdmin: makeChangeProxyAdmin(this._hre, defender), // block on defender - transferProxyAdminOwnership: makeTransferProxyAdminOwnership(this._hre, defender), // block on defender - }, - erc1967: { - getAdminAddress: (proxyAddress: string) => getAdminAddress(this._hre.network.provider, proxyAddress), - getImplementationAddress: (proxyAddress: string) => - getImplementationAddress(this._hre.network.provider, proxyAddress), - getBeaconAddress: (proxyAddress: string) => getBeaconAddress(this._hre.network.provider, proxyAddress), - }, - beacon: { - getImplementationAddress: (beaconAddress: string) => - getImplementationAddressFromBeacon(this._hre.network.provider, beaconAddress), - }, - // Properties from zksync - estimation: { - estimateGasProxy: makeUndefinedFunction(), - estimateGasBeacon: makeUndefinedFunction(), - estimateGasBeaconProxy: makeUndefinedFunction(), - }, - }; - } - - private makeDefenderFunctions() { - const { makeDeployContract } = require('@openzeppelin/hardhat-upgrades/dist/deploy-contract'); - const { - makeProposeUpgradeWithApproval, - } = require('@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'); - const { - makeGetDeployApprovalProcess, - makeGetUpgradeApprovalProcess, - } = require('@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'); - - const getUpgradeApprovalProcess = makeGetUpgradeApprovalProcess(this._hre); - - return { - ...this.makeFunctions(true), - // ...this.makeDefenderV1Functions(), - deployContract: makeDeployContract(this._hre, true), - proposeUpgradeWithApproval: makeProposeUpgradeWithApproval(this._hre, true), - getDeployApprovalProcess: makeGetDeployApprovalProcess(this._hre), - getUpgradeApprovalProcess, - getDefaultApprovalProcess: getUpgradeApprovalProcess, // deprecated, is an alias for getUpgradeApprovalProcess - }; - } - - private makeDefenderV1Functions() { - const { - makeVerifyDeploy, - makeVerifyDeployWithUploadedArtifact, - makeGetVerifyDeployBuildInfo, - makeGetVerifyDeployArtifact, - makeGetBytecodeDigest, - } = require('@openzeppelin/hardhat-upgrades/dist/defender-v1/verify-deployment'); - const { makeProposeUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/defender-v1/propose-upgrade'); - - return { - proposeUpgrade: makeProposeUpgrade(this._hre), - verifyDeployment: makeVerifyDeploy(this._hre), - verifyDeploymentWithUploadedArtifact: makeVerifyDeployWithUploadedArtifact(this._hre), - getDeploymentArtifact: makeGetVerifyDeployArtifact(this._hre), - getDeploymentBuildInfo: makeGetVerifyDeployBuildInfo(this._hre), - getBytecodeDigest: makeGetBytecodeDigest(this._hre), - }; - } - - private warnOnHardhatDefender() { - if (tryRequire('@openzeppelin/hardhat-defender', true)) { - const { logWarning } = require('@openzeppelin/upgrades-core'); - logWarning('The @openzeppelin/hardhat-defender package is deprecated.', [ - 'Uninstall the @openzeppelin/hardhat-defender package.', - 'OpenZeppelin Defender integration is included as part of the Hardhat Upgrades plugin.', - ]); - } - } -} diff --git a/packages/hardhat-zksync-upgradable/src/generator.ts b/packages/hardhat-zksync-upgradable/src/generator.ts new file mode 100644 index 000000000..6d484165b --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/generator.ts @@ -0,0 +1,22 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { ZkSyncGenerator } from './extension-generator'; +import { OpenzeppelinGenerator } from './openzeppelin-hardhat-upgrades/extension-generator'; + +export class ExtensionGenerator { + constructor(private _hre: HardhatRuntimeEnvironment) {} + + public populateExtension(): void { + if (this._hre.network.zksync) { + const zkSyncGenerator = new ZkSyncGenerator(this._hre); + zkSyncGenerator.populateExtension(); + return; + } + + const openzeppelinGenerators = new OpenzeppelinGenerator(this._hre); + openzeppelinGenerators.populateExtension(); + } +} + +export interface Generator { + populateExtension(): void; +} diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index 5e03661fd..35afb6a6c 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -1,4 +1,5 @@ import '@matterlabs/hardhat-zksync-solc'; +import '@nomicfoundation/hardhat-ethers'; import './type-extensions'; import { extendEnvironment, subtask, task, types } from 'hardhat/internal/core/config/config-env'; @@ -15,7 +16,7 @@ import { TASK_UPGRADE_ZKSYNC_PROXY, } from './task-names'; import { deployZkSyncBeacon, deployZkSyncProxy, upgradeZkSyncBeacon, upgradeZkSyncProxy } from './task-actions'; -import { ExtensionGenerator } from './extension-generator'; +import { ExtensionGenerator } from './generator'; extendEnvironment((hre) => { const extesionGenerator = new ExtensionGenerator(hre); diff --git a/packages/hardhat-zksync-upgradable/src/interfaces.ts b/packages/hardhat-zksync-upgradable/src/interfaces.ts index 9df5f5eff..2f6ae873c 100644 --- a/packages/hardhat-zksync-upgradable/src/interfaces.ts +++ b/packages/hardhat-zksync-upgradable/src/interfaces.ts @@ -1,37 +1,7 @@ -import { silenceWarnings, SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; +import { SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; import * as zk from 'zksync-ethers'; -import { DeployFunction as DeployFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy'; -import { PrepareUpgradeFunction as PrepareUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'; -import { UpgradeFunction as UpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'; -import { DeployBeaconFunction as DeployBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; -import { DeployBeaconProxyFunction as DeployBeaconProxyFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; -import { UpgradeBeaconFunction as UpgradeBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; -import { ForceImportFunction as ForceImportFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/force-import'; -import { - ChangeAdminFunction as ChangeAdminFunctionOZ, - TransferProxyAdminOwnershipFunction as TransferProxyAdminOwnershipFunctionOZ, - GetInstanceFunction as GetInstanceFunctionOZ, -} from '@openzeppelin/hardhat-upgrades/dist/admin'; -import { ValidateImplementationFunction as ValidateImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; -import { ValidateUpgradeFunction as ValidateUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; -import { DeployImplementationFunction as DeployImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-implementation'; -import { DeployContractFunction as DeployContractFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-contract'; -import { - GetDeployApprovalProcessFunction as GetDeployApprovalProcessFunctionOZ, - GetUpgradeApprovalProcessFunction as GetUpgradeApprovalProcessFunctionOZ, -} from '@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'; - -// import type { ProposeUpgradeFunction as ProposeUpgradeFunctionOZ} from '@openzeppelin/hardhat-upgrades/dist/defender-v1/propose-upgrade'; -// import type { -// VerifyDeployFunction as VerifyDeployFunctionOZ, -// VerifyDeployWithUploadedArtifactFunction as VerifyDeployWithUploadedArtifactFunctionOZ, -// GetVerifyDeployArtifactFunction as GetVerifyDeployArtifactFunctionOZ, -// GetVerifyDeployBuildInfoFunction as GetVerifyDeployBuildInfoFunctionOZ, -// GetBytecodeDigestFunction as GetBytecodeDigestFunctionOZ, -// } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/verify-deployment'; - import { UpgradeProxyArtifact, UpgradeProxyFactory } from './proxy-upgrade/upgrade-proxy'; import { UpgradeBeaconArtifact, UpgradeBeaconFactory } from './proxy-upgrade/upgrade-beacon'; import { @@ -46,69 +16,7 @@ import { EstimateBeaconGasFunction } from './gas-estimation/estimate-gas-beacon- import { ChangeAdminFunction, GetInstanceFunction, TransferProxyAdminOwnershipFunction } from './admin'; import { ValidateImplementationOptions } from './utils/options'; import { DeployAdminFunction } from './proxy-deployment/deploy-proxy-admin'; - -export type UndefinedFunctionType = (...args: any[]) => any; - -export function makeUndefinedFunction(): UndefinedFunctionType { - return (..._: any[]) => { - throw new Error('This function is not implemented'); - }; -} - -export interface HardhatUpgradesOZ { - deployProxy: DeployFunctionOZ; - upgradeProxy: UpgradeFunctionOZ; - validateImplementation: ValidateImplementationFunctionOZ; - validateUpgrade: ValidateUpgradeFunctionOZ; - deployImplementation: DeployImplementationFunctionOZ; - prepareUpgrade: PrepareUpgradeFunctionOZ; - deployBeacon: DeployBeaconFunctionOZ; - deployBeaconProxy: DeployBeaconProxyFunctionOZ; - upgradeBeacon: UpgradeBeaconFunctionOZ; - forceImport: ForceImportFunctionOZ; - silenceWarnings: typeof silenceWarnings; - admin: { - // property from zksync - getInstance: GetInstanceFunctionOZ; - changeProxyAdmin: ChangeAdminFunctionOZ; - transferProxyAdminOwnership: TransferProxyAdminOwnershipFunctionOZ; - }; - erc1967: { - getAdminAddress: (proxyAdress: string) => Promise; - getImplementationAddress: (proxyAdress: string) => Promise; - getBeaconAddress: (proxyAdress: string) => Promise; - }; - beacon: { - getImplementationAddress: (beaconAddress: string) => Promise; - }; - // Properties from zksync - deployProxyAdmin: UndefinedFunctionType; - estimation: { - estimateGasProxy: UndefinedFunctionType; - estimateGasBeacon: UndefinedFunctionType; - estimateGasBeaconProxy: UndefinedFunctionType; - }; -} - -// export type DefenderV1HardhatUpgradesOZ = { -// proposeUpgrade: ProposeUpgradeFunctionOZ; -// verifyDeployment: VerifyDeployFunctionOZ; -// verifyDeploymentWithUploadedArtifact: VerifyDeployWithUploadedArtifactFunctionOZ; -// getDeploymentArtifact: GetVerifyDeployArtifactFunctionOZ; -// getDeploymentBuildInfo: GetVerifyDeployBuildInfoFunctionOZ; -// getBytecodeDigest: GetBytecodeDigestFunctionOZ; -// } - -export type DefenderHardhatUpgradesOZ = { - deployContract: DeployContractFunctionOZ; - proposeUpgradeWithApproval: any; - getDeployApprovalProcess: GetDeployApprovalProcessFunctionOZ; - getUpgradeApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; - /** - * @deprecated Use `getUpgradeApprovalProcess` instead. - */ - getDefaultApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; -} & HardhatUpgradesOZ; +import { UndefinedFunctionType } from './utils'; export type ValidateImplementationFunction = ( ImplFactory: zk.ContractFactory, diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts new file mode 100644 index 000000000..6ab725051 --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts @@ -0,0 +1,103 @@ +import { + getImplementationAddress, + isBeaconProxy, + isTransparentOrUUPSProxy, + isTransparentProxy, +} from '@openzeppelin/upgrades-core'; +import { ProposalResponse, CreateProposalRequest } from '@openzeppelin/defender-admin-client'; +import { ContractFactory, getCreateAddress, ethers } from 'ethers'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { getAdminClient, getNetwork } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/utils'; +import { UpgradeOptions } from '@openzeppelin/hardhat-upgrades/dist/utils/options'; +import type { VerificationResponse } from './verify-deployment'; + +export interface ExtendedProposalResponse extends ProposalResponse { + txResponse?: ethers.TransactionResponse; + verificationResponse?: VerificationResponse; +} + +export type ProposeUpgradeFunction = ( + proxyAddress: string, + contractNameOrImplFactory: string | ContractFactory, + opts?: ProposalOptions, +) => Promise; + +export interface ProposalOptions extends UpgradeOptions { + title?: string; + description?: string; + proxyAdmin?: string; + multisig?: string; + multisigType?: CreateProposalRequest['viaType']; + bytecodeVerificationReferenceUrl?: string; +} + +export function makeProposeUpgrade(hre: HardhatRuntimeEnvironment): ProposeUpgradeFunction { + return async function proposeUpgrade(proxyAddress, contractNameOrImplFactory, opts = {}) { + const client = getAdminClient(hre); + const network = await getNetwork(hre); + + const { title, description, proxyAdmin, multisig, multisigType, ...moreOpts } = opts; + + if (await isBeaconProxy(hre.network.provider, proxyAddress)) { + throw new Error(`Beacon proxy is not currently supported with defender.proposeUpgrade()`); + } else if ( + !multisig && + (await isTransparentOrUUPSProxy(hre.network.provider, proxyAddress)) && + !(await isTransparentProxy(hre.network.provider, proxyAddress)) + ) { + throw new Error(`Multisig address is a required property for UUPS proxies`); + } else { + // try getting the implementation address so that it will give an error if it's not a transparent/uups proxy + await getImplementationAddress(hre.network.provider, proxyAddress); + } + + const implFactory = + typeof contractNameOrImplFactory === 'string' + ? await hre.ethers.getContractFactory(contractNameOrImplFactory) + : contractNameOrImplFactory; + const contractName = typeof contractNameOrImplFactory === 'string' ? contractNameOrImplFactory : undefined; + const contract = { address: proxyAddress, network, abi: implFactory.interface.formatJson() }; + + const prepareUpgradeResult = await hre.upgrades.prepareUpgrade(proxyAddress, implFactory, { + getTxResponse: true, + ...moreOpts, + }); + + let txResponse; + let newImplementation; + + if (typeof prepareUpgradeResult === 'string') { + newImplementation = prepareUpgradeResult; + } else { + txResponse = prepareUpgradeResult; + newImplementation = getCreateAddress(txResponse); + } + + const verificationResponse = + contractName && opts.bytecodeVerificationReferenceUrl + ? await hre.defender.verifyDeployment( + newImplementation, + contractName, + opts.bytecodeVerificationReferenceUrl, + ) + : undefined; + + const proposalResponse = await client.proposeUpgrade( + { + newImplementation, + title, + description, + proxyAdmin, + via: multisig, + viaType: multisigType, + }, + contract, + ); + + return { + ...proposalResponse, + txResponse, + verificationResponse, + }; + }; +} diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts new file mode 100644 index 000000000..64a48b5dc --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts @@ -0,0 +1,100 @@ +import { AdminClient, VerificationRequest } from '@openzeppelin/defender-admin-client'; +import { Artifact, BuildInfo, CompilerOutputBytecode, HardhatRuntimeEnvironment } from 'hardhat/types'; +import { getAdminClient, getNetwork } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/utils'; +import { sha256FromString } from 'ethereumjs-util'; + +export type VerificationResponse = Awaited>; + +type ExtendedArtifact = Artifact & { immutableReferences: CompilerOutputBytecode['immutableReferences'] }; + +export type VerifyDeployFunction = ( + address: string, + contractName: string, + referenceUrl: string, +) => Promise; + +export type VerifyDeployWithUploadedArtifactFunction = ( + address: string, + contractName: string, + artifactUri: string, +) => Promise; + +export type GetVerifyDeployArtifactFunction = (contractName: string) => Promise; + +export type GetVerifyDeployBuildInfoFunction = (contractName: string) => Promise; + +export type GetBytecodeDigestFunction = (contractName: string) => Promise; + +export function makeVerifyDeploy(hre: HardhatRuntimeEnvironment): VerifyDeployFunction { + return async function verifyDeploy(address, contractName, referenceUri) { + const client = getAdminClient(hre); + const contractNetwork = await getNetwork(hre); + const artifact = await getExtendedArtifact(hre, contractName); + + const request: VerificationRequest = { + contractAddress: address, + contractName: artifact.contractName, + solidityFilePath: artifact.sourceName, + contractNetwork, + artifactPayload: JSON.stringify(artifact), + referenceUri, + }; + + return client.verifyDeployment(request); + }; +} + +export function makeVerifyDeployWithUploadedArtifact( + hre: HardhatRuntimeEnvironment, +): VerifyDeployWithUploadedArtifactFunction { + return async function verifyDeploy(address, contractName, artifactUri) { + const client = getAdminClient(hre); + const contractNetwork = await getNetwork(hre); + const artifact = await hre.artifacts.readArtifact(contractName); + + const request: VerificationRequest = { + contractAddress: address, + contractName: artifact.contractName, + solidityFilePath: artifact.sourceName, + artifactUri, + contractNetwork, + }; + + return client.verifyDeployment(request); + }; +} + +export function makeGetVerifyDeployArtifact(hre: HardhatRuntimeEnvironment): GetVerifyDeployArtifactFunction { + return async function getVerifyDeployArtifact(contractName: string): Promise { + return getExtendedArtifact(hre, contractName); + }; +} + +export function makeGetVerifyDeployBuildInfo(hre: HardhatRuntimeEnvironment): GetVerifyDeployBuildInfoFunction { + return async function getVerifyDeployBuildInfo(contractName: string): Promise { + const artifact = await hre.artifacts.readArtifact(contractName); + const fqn = `${artifact.sourceName}:${artifact.contractName}`; + const buildInfo = await hre.artifacts.getBuildInfo(fqn); + if (!buildInfo) { + throw new Error(`Build info for ${fqn} not found`); + } + return buildInfo; + }; +} + +export function makeGetBytecodeDigest(hre: HardhatRuntimeEnvironment) { + return async function getBytecodeDigest(contractName: string): Promise { + const artifact = await hre.artifacts.readArtifact(contractName); + const bytecode = artifact.deployedBytecode; + return sha256FromString(bytecode).toString('hex'); + }; +} + +async function getExtendedArtifact(hre: HardhatRuntimeEnvironment, contractName: string): Promise { + const artifact = await hre.artifacts.readArtifact(contractName); + const fqn = `${artifact.sourceName}:${artifact.contractName}`; + const buildInfo = await hre.artifacts.getBuildInfo(fqn); + const contractBuildInfo = buildInfo?.output.contracts[artifact.sourceName][artifact.contractName]; + const immutableReferences = contractBuildInfo?.evm.deployedBytecode.immutableReferences ?? {}; + return { ...artifact, immutableReferences }; +} diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts new file mode 100644 index 000000000..8d4dd3350 --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts @@ -0,0 +1,133 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { lazyObject } from 'hardhat/plugins'; +import { makeUndefinedFunction, tryRequire } from '../utils'; +import { HardhatZksyncUpgrades } from '../interfaces'; +import { Generator } from '../generator'; +import { HardhatUpgradesOZ } from './interfaces'; + +export class OpenzeppelinGenerator implements Generator { + constructor(private _hre: HardhatRuntimeEnvironment) {} + + public populateExtension(): void { + this._hre.upgrades = lazyObject(() => this.makeFunctions(false) as HardhatUpgradesOZ & HardhatZksyncUpgrades); + this.warnOnHardhatDefender(); + this._hre.defender = lazyObject(() => this.makeDefenderFunctions()); + } + + private makeFunctions(defender: boolean): HardhatUpgradesOZ { + const { + getImplementationAddressFromBeacon, + silenceWarnings, + } = require('@openzeppelin/upgrades-core/dist/impl-address'); + const { + getAdminAddress, + getImplementationAddress, + getBeaconAddress, + } = require('@openzeppelin/upgrades-core/dist/eip-1967'); + const { makeDeployProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy'); + const { makeUpgradeProxy } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'); + const { makeValidateImplementation } = require('@openzeppelin/hardhat-upgrades/dist/validate-implementation'); + const { makeValidateUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/validate-upgrade'); + const { makeDeployImplementation } = require('@openzeppelin/hardhat-upgrades/dist/deploy-implementation'); + const { makePrepareUpgrade } = require('@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'); + const { makeDeployBeacon } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon'); + const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); + const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); + const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); + const { makeDeployProxyAdmin } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'); + const { + makeChangeProxyAdmin, + makeTransferProxyAdminOwnership, + makeGetInstanceFunction, + } = require('@openzeppelin/hardhat-upgrades/dist/admin'); + + return { + silenceWarnings, + deployProxy: makeDeployProxy(this._hre, defender), + upgradeProxy: makeUpgradeProxy(this._hre, defender), // block on defender + validateImplementation: makeValidateImplementation(this._hre), + validateUpgrade: makeValidateUpgrade(this._hre), + deployImplementation: makeDeployImplementation(this._hre, defender), + prepareUpgrade: makePrepareUpgrade(this._hre, defender), + deployBeacon: makeDeployBeacon(this._hre, defender), // block on defender + deployBeaconProxy: makeDeployBeaconProxy(this._hre, defender), + deployProxyAdmin: makeDeployProxyAdmin(this._hre, defender), + upgradeBeacon: makeUpgradeBeacon(this._hre, defender), // block on defender + forceImport: makeForceImport(this._hre), + admin: { + getInstance: makeGetInstanceFunction(this._hre, defender), // block on defender + changeProxyAdmin: makeChangeProxyAdmin(this._hre, defender), // block on defender + transferProxyAdminOwnership: makeTransferProxyAdminOwnership(this._hre, defender), // block on defender + }, + erc1967: { + getAdminAddress: (proxyAddress: string) => getAdminAddress(this._hre.network.provider, proxyAddress), + getImplementationAddress: (proxyAddress: string) => + getImplementationAddress(this._hre.network.provider, proxyAddress), + getBeaconAddress: (proxyAddress: string) => getBeaconAddress(this._hre.network.provider, proxyAddress), + }, + beacon: { + getImplementationAddress: (beaconAddress: string) => + getImplementationAddressFromBeacon(this._hre.network.provider, beaconAddress), + }, + // Properties from zksync + estimation: { + estimateGasProxy: makeUndefinedFunction(), + estimateGasBeacon: makeUndefinedFunction(), + estimateGasBeaconProxy: makeUndefinedFunction(), + }, + }; + } + + private makeDefenderFunctions() { + const { makeDeployContract } = require('@openzeppelin/hardhat-upgrades/dist/deploy-contract'); + const { + makeProposeUpgradeWithApproval, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/propose-upgrade-with-approval'); + const { + makeGetDeployApprovalProcess, + makeGetUpgradeApprovalProcess, + } = require('@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'); + + const getUpgradeApprovalProcess = makeGetUpgradeApprovalProcess(this._hre); + + return { + ...this.makeFunctions(true), + ...this.makeDefenderV1Functions(), + deployContract: makeDeployContract(this._hre, true), + proposeUpgradeWithApproval: makeProposeUpgradeWithApproval(this._hre, true), + getDeployApprovalProcess: makeGetDeployApprovalProcess(this._hre), + getUpgradeApprovalProcess, + getDefaultApprovalProcess: getUpgradeApprovalProcess, // deprecated, is an alias for getUpgradeApprovalProcess + }; + } + + private makeDefenderV1Functions() { + const { + makeVerifyDeploy, + makeVerifyDeployWithUploadedArtifact, + makeGetVerifyDeployBuildInfo, + makeGetVerifyDeployArtifact, + makeGetBytecodeDigest, + } = require('./defender-v1/verify-deployment'); + const { makeProposeUpgrade } = require('./defender-v1/propose-upgrade'); + + return { + proposeUpgrade: makeProposeUpgrade(this._hre), + verifyDeployment: makeVerifyDeploy(this._hre), + verifyDeploymentWithUploadedArtifact: makeVerifyDeployWithUploadedArtifact(this._hre), + getDeploymentArtifact: makeGetVerifyDeployArtifact(this._hre), + getDeploymentBuildInfo: makeGetVerifyDeployBuildInfo(this._hre), + getBytecodeDigest: makeGetBytecodeDigest(this._hre), + }; + } + + private warnOnHardhatDefender() { + if (tryRequire('@openzeppelin/hardhat-defender', true)) { + const { logWarning } = require('@openzeppelin/upgrades-core'); + logWarning('The @openzeppelin/hardhat-defender package is deprecated.', [ + 'Uninstall the @openzeppelin/hardhat-defender package.', + 'OpenZeppelin Defender integration is included as part of the Hardhat Upgrades plugin.', + ]); + } + } +} diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts new file mode 100644 index 000000000..f975ac075 --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts @@ -0,0 +1,89 @@ +import { silenceWarnings } from '@openzeppelin/upgrades-core'; + +import { DeployFunction as DeployFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy'; +import { PrepareUpgradeFunction as PrepareUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/prepare-upgrade'; +import { UpgradeFunction as UpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-proxy'; +import { DeployBeaconFunction as DeployBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; +import { DeployBeaconProxyFunction as DeployBeaconProxyFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; +import { UpgradeBeaconFunction as UpgradeBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; +import { DeployAdminFunction as DeployAdminFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'; +import { ForceImportFunction as ForceImportFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/force-import'; +import { + ChangeAdminFunction as ChangeAdminFunctionOZ, + TransferProxyAdminOwnershipFunction as TransferProxyAdminOwnershipFunctionOZ, + GetInstanceFunction as GetInstanceFunctionOZ, +} from '@openzeppelin/hardhat-upgrades/dist/admin'; +import { ValidateImplementationFunction as ValidateImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; +import { ValidateUpgradeFunction as ValidateUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; +import { DeployImplementationFunction as DeployImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-implementation'; +import { DeployContractFunction as DeployContractFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-contract'; +import { + GetDeployApprovalProcessFunction as GetDeployApprovalProcessFunctionOZ, + GetUpgradeApprovalProcessFunction as GetUpgradeApprovalProcessFunctionOZ, +} from '@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'; + +import type { ProposeUpgradeFunction as ProposeUpgradeFunctionOZ } from '../openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade'; +import type { + VerifyDeployFunction as VerifyDeployFunctionOZ, + VerifyDeployWithUploadedArtifactFunction as VerifyDeployWithUploadedArtifactFunctionOZ, + GetVerifyDeployArtifactFunction as GetVerifyDeployArtifactFunctionOZ, + GetVerifyDeployBuildInfoFunction as GetVerifyDeployBuildInfoFunctionOZ, + GetBytecodeDigestFunction as GetBytecodeDigestFunctionOZ, +} from '../openzeppelin-hardhat-upgrades/defender-v1/verify-deployment'; +import { UndefinedFunctionType } from '../utils'; + +export interface HardhatUpgradesOZ { + deployProxy: DeployFunctionOZ; + upgradeProxy: UpgradeFunctionOZ; + validateImplementation: ValidateImplementationFunctionOZ; + validateUpgrade: ValidateUpgradeFunctionOZ; + deployImplementation: DeployImplementationFunctionOZ; + prepareUpgrade: PrepareUpgradeFunctionOZ; + deployBeacon: DeployBeaconFunctionOZ; + deployBeaconProxy: DeployBeaconProxyFunctionOZ; + upgradeBeacon: UpgradeBeaconFunctionOZ; + deployProxyAdmin: DeployAdminFunctionOZ; + forceImport: ForceImportFunctionOZ; + silenceWarnings: typeof silenceWarnings; + admin: { + // property from zksync + getInstance: GetInstanceFunctionOZ; + changeProxyAdmin: ChangeAdminFunctionOZ; + transferProxyAdminOwnership: TransferProxyAdminOwnershipFunctionOZ; + }; + erc1967: { + getAdminAddress: (proxyAdress: string) => Promise; + getImplementationAddress: (proxyAdress: string) => Promise; + getBeaconAddress: (proxyAdress: string) => Promise; + }; + beacon: { + getImplementationAddress: (beaconAddress: string) => Promise; + }; + // Properties from zksync + estimation: { + estimateGasProxy: UndefinedFunctionType; + estimateGasBeacon: UndefinedFunctionType; + estimateGasBeaconProxy: UndefinedFunctionType; + }; +} + +export interface DefenderV1HardhatUpgradesOZ { + proposeUpgrade: ProposeUpgradeFunctionOZ; + verifyDeployment: VerifyDeployFunctionOZ; + verifyDeploymentWithUploadedArtifact: VerifyDeployWithUploadedArtifactFunctionOZ; + getDeploymentArtifact: GetVerifyDeployArtifactFunctionOZ; + getDeploymentBuildInfo: GetVerifyDeployBuildInfoFunctionOZ; + getBytecodeDigest: GetBytecodeDigestFunctionOZ; +} + +export type DefenderHardhatUpgradesOZ = { + deployContract: DeployContractFunctionOZ; + proposeUpgradeWithApproval: any; + getDeployApprovalProcess: GetDeployApprovalProcessFunctionOZ; + getUpgradeApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; + /** + * @deprecated Use `getUpgradeApprovalProcess` instead. + */ + getDefaultApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; +} & HardhatUpgradesOZ & + DefenderV1HardhatUpgradesOZ; diff --git a/packages/hardhat-zksync-upgradable/src/type-extensions.ts b/packages/hardhat-zksync-upgradable/src/type-extensions.ts index dbad8cb7b..6809e7212 100644 --- a/packages/hardhat-zksync-upgradable/src/type-extensions.ts +++ b/packages/hardhat-zksync-upgradable/src/type-extensions.ts @@ -1,5 +1,6 @@ import 'hardhat/types/runtime'; -import { DefenderHardhatUpgradesOZ, HardhatUpgradesOZ, HardhatZksyncUpgrades } from './interfaces'; +import { HardhatZksyncUpgrades } from './interfaces'; +import { DefenderHardhatUpgradesOZ, HardhatUpgradesOZ } from './openzeppelin-hardhat-upgrades/interfaces'; declare module 'hardhat/types/runtime' { export interface HardhatRuntimeEnvironment { @@ -8,3 +9,20 @@ declare module 'hardhat/types/runtime' { defender: DefenderHardhatUpgradesOZ; } } + +// Openzeppelin Defender plugin +export interface HardhatDefenderConfig { + apiKey: string; + apiSecret: string; + useDefenderDeploy?: boolean; +} + +declare module 'hardhat/types/config' { + export interface HardhatUserConfig { + defender?: HardhatDefenderConfig; + } + + export interface HardhatConfig { + defender?: HardhatDefenderConfig; + } +} diff --git a/packages/hardhat-zksync-upgradable/src/utils.ts b/packages/hardhat-zksync-upgradable/src/utils.ts index 33a9e102c..1d9688b05 100644 --- a/packages/hardhat-zksync-upgradable/src/utils.ts +++ b/packages/hardhat-zksync-upgradable/src/utils.ts @@ -81,3 +81,11 @@ export function tryRequire(id: string, resolveOnly?: boolean) { } return false; } + +export type UndefinedFunctionType = (...args: any[]) => any; + +export function makeUndefinedFunction(): UndefinedFunctionType { + return (..._: any[]) => { + throw new Error('This function is not implemented'); + }; +} diff --git a/packages/hardhat-zksync-upgradable/test/constants.ts b/packages/hardhat-zksync-upgradable/test/constants.ts index d738253eb..ae161e0ec 100644 --- a/packages/hardhat-zksync-upgradable/test/constants.ts +++ b/packages/hardhat-zksync-upgradable/test/constants.ts @@ -18,7 +18,8 @@ export const storageLayoutErrors = { RENAMED_VARIABLE: 'Renamed `thirdValue` to `renamedValue`', DELETED_VARIABLE: 'Deleted `fifthValue`', CHANGE_VARIABLE_TYPE: 'Upgraded `secondValue` to an incompatible type', - STORAGE_GAP_SIZE: 'Layout changed for `__gap`', + STORAGE_GAP_SIZE: 'Bad storage gap resize from 10 to 9', + STORAGE_GAP_RESIZE: 'Upgraded `__gap` to an incompatible type', }; export const TEST_ADDRESS = '0x8e1DC7E4Bb15927E76a854a92Bf8053761501fdC'; diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2.sol index c5cf38c67..eb31ff339 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2.sol @@ -7,9 +7,9 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; contract BoxWithStorageGapV2 is Initializable { uint256 private value; uint256 private secondValue; - address private newAddress; - uint256[9] private __gap; + uint256[10] private __gap; uint256 private thirdValue; + address private newAddress; // Emitted when the stored value changes event ValueChanged(uint256 newValue); diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2Invalid.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2Invalid.sol index 5570c479d..09b9add28 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2Invalid.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/storage-layout-validations/contracts/BoxWithStorageGapV2Invalid.sol @@ -7,9 +7,9 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; contract BoxWithStorageGapV2Invalid is Initializable { uint256 private value; uint256 private secondValue; - address private newAddress; - uint256[10] private __gap; + uint256[9] private __gap; uint256 private thirdValue; + address private newAddress; // Emitted when the stored value changes event ValueChanged(uint256 newValue); diff --git a/packages/hardhat-zksync-upgradable/test/tests.ts b/packages/hardhat-zksync-upgradable/test/tests.ts index bc428217e..99772df49 100644 --- a/packages/hardhat-zksync-upgradable/test/tests.ts +++ b/packages/hardhat-zksync-upgradable/test/tests.ts @@ -482,7 +482,7 @@ describe('Upgradable plugin tests', function () { boxV2Artifact, ), (error: any) => - error.message.includes(storageLayoutErrors.INCOMPATIBLE_STORAGE_LAYOUT) && + error.message.includes(storageLayoutErrors.STORAGE_GAP_RESIZE) && error.message.includes(storageLayoutErrors.STORAGE_GAP_SIZE), ); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39ff24c67..da759af2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1333,9 +1333,15 @@ importers: '@matterlabs/hardhat-zksync-solc': specifier: workspace:^ version: link:../hardhat-zksync-solc + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.6 + version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts-hardhat-zksync-upgradable': specifier: npm:@openzeppelin/contracts@^4.9.2 version: '@openzeppelin/contracts@4.9.6' + '@openzeppelin/defender-admin-client': + specifier: ^1.52.0 + version: 1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10) '@openzeppelin/hardhat-upgrades': specifier: ~2.5.1 version: 2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) From 48e0a9cf330926cfb66faacbb9ac27423168e941 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Thu, 15 Aug 2024 14:15:24 +0200 Subject: [PATCH 06/20] fix: compile missing contracts before verify --- .../hardhat-zksync-upgradable/src/utils.ts | 46 ++++++++++++------- .../src/verify/verify-proxy.ts | 4 ++ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/utils.ts b/packages/hardhat-zksync-upgradable/src/utils.ts index 1d9688b05..1ab017f83 100644 --- a/packages/hardhat-zksync-upgradable/src/utils.ts +++ b/packages/hardhat-zksync-upgradable/src/utils.ts @@ -24,29 +24,41 @@ export function wrapMakeFunction( wrappedFunction: (...args: any) => T, ): (...args: any) => Promise { return async function (...args: any): Promise { - try { - if (!isOpenzeppelinContractsVersionValid()) { - throw new Error(OZ_CONTRACTS_VERISION_INCOMPATIBLE_ERROR); - } - } catch (e: any) { - console.warn(chalk.yellow(e.message)); - } + checkOpenzeppelinVersion(); - const upgradableContracts = getUpgradableContracts(); - hre.config.zksolc.settings.overrideContractsToCompile = [ - upgradableContracts.ProxyAdmin, - upgradableContracts.TransparentUpgradeableProxy, - upgradableContracts.BeaconProxy, - upgradableContracts.UpgradeableBeacon, - upgradableContracts.ERC1967Proxy, - ]; - await hre.run('compile', { quiet: true }); - hre.config.zksolc.settings.overrideContractsToCompile = undefined; + await compileProxyContracts(hre); return wrappedFunction(...args); }; } +function checkOpenzeppelinVersion() { + try { + if (!isOpenzeppelinContractsVersionValid()) { + throw new Error(OZ_CONTRACTS_VERISION_INCOMPATIBLE_ERROR); + } + } catch (e: any) { + console.warn(chalk.yellow(e.message)); + } +} + +export async function compileProxyContracts(hre: HardhatRuntimeEnvironment, noCompile: boolean = false) { + if (noCompile) { + return; + } + + const upgradableContracts = getUpgradableContracts(); + hre.config.zksolc.settings.overrideContractsToCompile = [ + upgradableContracts.ProxyAdmin, + upgradableContracts.TransparentUpgradeableProxy, + upgradableContracts.BeaconProxy, + upgradableContracts.UpgradeableBeacon, + upgradableContracts.ERC1967Proxy, + ]; + await hre.run('compile', { quiet: true }); + delete hre.config.zksolc.settings.overrideContractsToCompile; +} + export function isOpenzeppelinContractsVersionValid(): boolean { try { // eslint-disable-next-line import/no-extraneous-dependencies diff --git a/packages/hardhat-zksync-upgradable/src/verify/verify-proxy.ts b/packages/hardhat-zksync-upgradable/src/verify/verify-proxy.ts index 5dfa7a339..0226e667c 100644 --- a/packages/hardhat-zksync-upgradable/src/verify/verify-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/verify/verify-proxy.ts @@ -9,6 +9,7 @@ import { EVENT_NOT_FOUND_ERROR, UPGRADE_VERIFY_ERROR } from '../constants'; import { getContractCreationTxHash } from '../utils/utils-general'; import { VerifiableContractInfo } from '../interfaces'; import { ZkSyncUpgradablePluginError } from '../errors'; +import { compileProxyContracts } from '../utils'; import { fullVerifyTransparentOrUUPS } from './verify-transparent-uups'; import { fullVerifyBeacon, fullVerifyBeaconProxy } from './verify-beacon'; @@ -29,10 +30,13 @@ export async function verify(args: any, hre: HardhatRuntimeEnvironment, runSuper const proxyAddress = args.address; if (await isTransparentOrUUPSProxy(provider, proxyAddress)) { + await compileProxyContracts(hre, args.noCompile); await fullVerifyTransparentOrUUPS(hre, proxyAddress, hardhatZkSyncVerify, runSuper, args.noCompile); } else if (await isBeaconProxy(provider, proxyAddress)) { + await compileProxyContracts(hre, args.noCompile); await fullVerifyBeaconProxy(hre, proxyAddress, hardhatZkSyncVerify, runSuper, args.noCompile); } else if (await isBeacon(provider, proxyAddress)) { + await compileProxyContracts(hre, args.noCompile); await fullVerifyBeacon(hre, proxyAddress, hardhatZkSyncVerify, runSuper, args.noCompile); } else { return hardhatZkSyncVerify(proxyAddress); From 604d0e048c2f865293a6c74bd266659df0b2ed0d Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Mon, 19 Aug 2024 13:16:07 +0200 Subject: [PATCH 07/20] fix: update check for contracts update --- .../src/proxy-upgrade/upgrade-beacon.ts | 2 +- .../src/proxy-upgrade/upgrade-proxy.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts index 084e09f2b..86f3cb6ce 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts @@ -103,7 +103,7 @@ async function upgradeBeacon( export function makeUpgradeBeacon(hre: HardhatRuntimeEnvironment): UpgradeBeaconArtifact | UpgradeBeaconFactory { return async function (...args: Parameters): Promise { - const target = args[0]; + const target = args[1]; if (target instanceof zk.ContractFactory) { return await upgradeBeaconFactory(hre, ...(args as Parameters)); } else { diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts index ab29da370..530435641 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts @@ -36,8 +36,8 @@ type Upgrader = (nextImpl: string, call?: string) => Promise): Promise { - const target = args[0]; - if (target instanceof zk.ContractFactory || args[1] instanceof zk.ContractFactory) { + const target = args[1]; + if (target instanceof zk.ContractFactory) { return await upgradeProxyFactory(hre, ...(args as Parameters)); } else { return upgradeProxyArtifact(hre, ...(args as Parameters)); From dfb12bce87ad73b7f4c9b01585e5158dd0a99d8f Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 27 Aug 2024 00:09:38 +0200 Subject: [PATCH 08/20] fix: add paymaster params for proxy and implementation deployment --- .../src/proxy-deployment/deploy-beacon-proxy.ts | 1 + .../src/proxy-deployment/deploy-impl.ts | 4 ++++ .../src/proxy-deployment/deploy-proxy.ts | 1 + packages/hardhat-zksync-upgradable/src/utils/options.ts | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts index baa1e3499..5adab67f9 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts @@ -141,6 +141,7 @@ async function deployBeaconProxy( ...(await deploy(beaconProxyFactory, beaconAddress, data, { customData: { salt: opts.salt, + paymasterParams: opts.paymasterParams, }, })), }; diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts index c06184d39..ba69db4c6 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts @@ -91,6 +91,10 @@ async function deployImpl 'salt' in opts ? (opts as UpgradeOptions).salt : (opts as UpgradeOptions).saltImpl, + paymasterParams: + 'paymasterParams' in opts + ? (opts as UpgradeOptions).paymasterParams + : (opts as UpgradeOptions).paymasterImplParams, }, }, ], diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts index fdfdd1498..41e75ec61 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts @@ -135,6 +135,7 @@ async function deployProxy( const customDataProxy = { customData: { salt: opts.saltProxy, + paymasterParams: opts.paymasterProxyParams, }, }; diff --git a/packages/hardhat-zksync-upgradable/src/utils/options.ts b/packages/hardhat-zksync-upgradable/src/utils/options.ts index c0b5d7299..a95b45317 100644 --- a/packages/hardhat-zksync-upgradable/src/utils/options.ts +++ b/packages/hardhat-zksync-upgradable/src/utils/options.ts @@ -8,6 +8,7 @@ import { } from '@openzeppelin/upgrades-core'; import { DeploymentType } from 'zksync-ethers/build/types'; +import { BytesLike } from 'ethers'; import { LOCAL_SETUP_ZKSYNC_NETWORK } from '../constants'; export type StandaloneOptions = @@ -26,10 +27,13 @@ export type DeploymentTypesOptions = From ee97c23f223aa9517e74fcd530e3b8503f8454fd Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 27 Aug 2024 14:10:19 +0200 Subject: [PATCH 09/20] fix: add paymaster params for admin and add other custom data --- packages/hardhat-zksync-upgradable/README.md | 26 +++++++++++++++++++ .../proxy-deployment/deploy-beacon-proxy.ts | 1 + .../src/proxy-deployment/deploy-impl.ts | 1 + .../proxy-deployment/deploy-proxy-admin.ts | 19 +++++++++++--- .../src/proxy-deployment/deploy-proxy.ts | 6 ++++- .../src/utils/options.ts | 10 ++++--- 6 files changed, 55 insertions(+), 8 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/README.md b/packages/hardhat-zksync-upgradable/README.md index 0f3b5d193..28adc738b 100644 --- a/packages/hardhat-zksync-upgradable/README.md +++ b/packages/hardhat-zksync-upgradable/README.md @@ -65,6 +65,19 @@ await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [initializerFuncti Permissible values for the deployment type include `create`, `create2`, `createAccount`, and `create2Account`. If this parameter is omitted, the default value will be `create`. If the salt parameters are ommited, the default value will be `0x0000000000000000000000000000000000000000000000000000000000000000`. +In the options section, paymaster parameters can be included for both proxy and implementation deployments. To do so, use: + - `paymasterProxyParams` + - `paymasterImplParams` + + ``` +await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [initializerFunctionArguments], + { initializer: "initialize", + paymasterProxyParams: params, + paymasterImplParams: params, + } +); +``` + - **Deploying UUPS proxies** The UUPS proxy pattern is similar to the transparent proxy pattern, except that the upgrade is triggered via the logic contract instead of from the proxy contract. @@ -119,6 +132,19 @@ const box = await hre.zkUpgrades.deployBeaconProxy(deployer.zkWallet, beacon, bo Permissible values for the deployment type include `create`, `create2`, `createAccount`, and `create2Account`. If this parameter is omitted, the default value will be `create`. If the salt parameters are ommited, the default value will be `0x0000000000000000000000000000000000000000000000000000000000000000`. +In the options section, you can include paymaster parameters. To do so, use +`paymasterParams` argument. + +``` +await hre.zkUpgrades.deployBeacon(deployer.zkWallet, boxContract, { + paymasterParams: params +}); + +const box = await hre.zkUpgrades.deployBeaconProxy(deployer.zkWallet, beacon, boxContract, [42], { + paymasterParams: params +}); + +``` - **Upgrading proxies** In order for a smart contract implementation to be upgradable, it has to follow specific [rules](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable). diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts index 5adab67f9..ea13c5282 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts @@ -142,6 +142,7 @@ async function deployBeaconProxy( customData: { salt: opts.salt, paymasterParams: opts.paymasterParams, + ...opts.otherCustomData, }, })), }; diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts index ba69db4c6..dabaabba5 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts @@ -95,6 +95,7 @@ async function deployImpl 'paymasterParams' in opts ? (opts as UpgradeOptions).paymasterParams : (opts as UpgradeOptions).paymasterImplParams, + ...opts.otherCustomData, }, }, ], diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts index 3e5018391..25eab7469 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts @@ -3,6 +3,7 @@ import * as zk from 'zksync-ethers'; import path from 'path'; import assert from 'assert'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; +import { DeploymentType } from 'zksync-ethers/build/types'; import { DeployProxyAdminOptions } from '../utils/options'; import { PROXY_ADMIN_JSON } from '../constants'; import { fetchOrDeployAdmin } from '../core/impl-store'; @@ -13,8 +14,14 @@ export type DeployAdminFunction = (wallet?: zk.Wallet, opts?: DeployProxyAdminOp export function makeDeployProxyAdmin(hre: HardhatRuntimeEnvironment): any { return async function deployProxyAdmin(wallet: zk.Wallet, opts: DeployProxyAdminOptions = {}) { - const adminFactory = await getAdminFactory(hre, wallet); - return await fetchOrDeployAdmin(wallet.provider, () => deploy(adminFactory), opts); + const adminFactory = await getAdminFactory(hre, wallet, opts.deploymentType); + const customData = { + salt: opts.salt, + paymasterParams: opts.paymasterParams, + ...opts.otherCustomData, + }; + + return await fetchOrDeployAdmin(wallet.provider, () => deploy(adminFactory, customData), opts); }; } @@ -29,7 +36,13 @@ export async function getAdminArtifact(hre: HardhatRuntimeEnvironment): Promise< export async function getAdminFactory( hre: HardhatRuntimeEnvironment, wallet: zk.Wallet, + deploymentType?: DeploymentType, ): Promise> { const proxyAdminContract = await getAdminArtifact(hre); - return new zk.ContractFactory(proxyAdminContract.abi, proxyAdminContract.bytecode, wallet); + return new zk.ContractFactory( + proxyAdminContract.abi, + proxyAdminContract.bytecode, + wallet, + deploymentType, + ); } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts index 41e75ec61..3c1959029 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts @@ -136,6 +136,7 @@ async function deployProxy( customData: { salt: opts.saltProxy, paymasterParams: opts.paymasterProxyParams, + ...opts.otherCustomData, }, }; @@ -178,7 +179,10 @@ async function deployProxy( } case 'transparent': { - const adminAddress = await hre.upgrades.deployProxyAdmin(wallet, {}); + const adminAddress = await hre.upgrades.deployProxyAdmin(wallet, { + paymasterParams: opts.paymasterProxyParams, + }); + if (!quiet) { console.info(chalk.green(`Admin was deployed to ${adminAddress}`)); } diff --git a/packages/hardhat-zksync-upgradable/src/utils/options.ts b/packages/hardhat-zksync-upgradable/src/utils/options.ts index a95b45317..f68954eba 100644 --- a/packages/hardhat-zksync-upgradable/src/utils/options.ts +++ b/packages/hardhat-zksync-upgradable/src/utils/options.ts @@ -18,11 +18,12 @@ export type StandaloneOptions; + } & CustomDataOptions; -export type DeploymentTypesOptions = +export type CustomDataOptions = TRequiredSeperateForProxy extends true | undefined ? { + otherCustomData?: any; deploymentTypeImpl?: DeploymentType; deploymentTypeProxy?: DeploymentType; saltImpl?: string; @@ -31,6 +32,7 @@ export type DeploymentTypesOptions; +export type DeployBeaconProxyOptions = ProxyKindOption & Initializer & CustomDataOptions; export type DeployBeaconOptions = StandaloneOptions; export type DeployImplementationOptions = StandaloneOptions; -export type DeployProxyAdminOptions = DeployOpts; +export type DeployProxyAdminOptions = DeployOpts & CustomDataOptions; export type DeployProxyOptions = StandaloneOptions & Initializer; export type UpgradeBeaconOptions = UpgradeOptions; export type UpgradeProxyOptions = UpgradeOptions & { From 9005368cd19d63735930cbacdd78b43113894220 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 27 Aug 2024 14:16:08 +0200 Subject: [PATCH 10/20] fix: add verify for non zksync networks --- packages/hardhat-zksync-upgradable/src/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index 35afb6a6c..87c42d979 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -97,6 +97,12 @@ subtask(TASK_COMPILE_SOLIDITY_COMPILE, async (args: RunCompilerArgs, hre, runSup }); subtask('verify:verify').setAction(async (args, hre, runSuper) => { + if (!hre.network.zksync) { + // eslint-disable-next-line @typescript-eslint/no-shadow + const { verify } = await import('@openzeppelin/hardhat-upgrades/dist/verify-proxy'); + return await verify(args, hre, runSuper); + } + const { verify } = await import('./verify/verify-proxy'); return await verify(args, hre, runSuper); }); From 6678eb17ec2b31e3d6ae173fbb29a2465ad17b79 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 28 Aug 2024 11:59:27 +0200 Subject: [PATCH 11/20] fix: change custom data for proxy admin --- .../src/proxy-deployment/deploy-proxy-admin.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts index 25eab7469..05a4ccbbf 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts @@ -15,13 +15,14 @@ export type DeployAdminFunction = (wallet?: zk.Wallet, opts?: DeployProxyAdminOp export function makeDeployProxyAdmin(hre: HardhatRuntimeEnvironment): any { return async function deployProxyAdmin(wallet: zk.Wallet, opts: DeployProxyAdminOptions = {}) { const adminFactory = await getAdminFactory(hre, wallet, opts.deploymentType); - const customData = { - salt: opts.salt, - paymasterParams: opts.paymasterParams, - ...opts.otherCustomData, - }; - return await fetchOrDeployAdmin(wallet.provider, () => deploy(adminFactory, customData), opts); + return await fetchOrDeployAdmin(wallet.provider, () => deploy(adminFactory, { + customData:{ + salt: opts.salt, + paymasterParams: opts.paymasterParams, + ...opts.otherCustomData, + } + }), opts); }; } From 671feb4df430918829b42902b0b0d5023e2dd1a5 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 28 Aug 2024 12:01:09 +0200 Subject: [PATCH 12/20] fix: change custom data for proxy admin --- .../proxy-deployment/deploy-proxy-admin.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts index 05a4ccbbf..2f19cb887 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts @@ -15,14 +15,18 @@ export type DeployAdminFunction = (wallet?: zk.Wallet, opts?: DeployProxyAdminOp export function makeDeployProxyAdmin(hre: HardhatRuntimeEnvironment): any { return async function deployProxyAdmin(wallet: zk.Wallet, opts: DeployProxyAdminOptions = {}) { const adminFactory = await getAdminFactory(hre, wallet, opts.deploymentType); - - return await fetchOrDeployAdmin(wallet.provider, () => deploy(adminFactory, { - customData:{ - salt: opts.salt, - paymasterParams: opts.paymasterParams, - ...opts.otherCustomData, - } - }), opts); + return await fetchOrDeployAdmin( + wallet.provider, + () => + deploy(adminFactory, { + customData: { + salt: opts.salt, + paymasterParams: opts.paymasterParams, + ...opts.otherCustomData, + }, + }), + opts, + ); }; } From 438e83403395b4654edb2a398a1c232c11440972 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 28 Aug 2024 15:26:08 +0200 Subject: [PATCH 13/20] fix: change paymaster params to PaymasterParams from zksync-ethers --- packages/hardhat-zksync-upgradable/src/utils/options.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/utils/options.ts b/packages/hardhat-zksync-upgradable/src/utils/options.ts index f68954eba..aa43a8e07 100644 --- a/packages/hardhat-zksync-upgradable/src/utils/options.ts +++ b/packages/hardhat-zksync-upgradable/src/utils/options.ts @@ -7,8 +7,7 @@ import { withValidationDefaults, } from '@openzeppelin/upgrades-core'; -import { DeploymentType } from 'zksync-ethers/build/types'; -import { BytesLike } from 'ethers'; +import { DeploymentType, PaymasterParams } from 'zksync-ethers/build/types'; import { LOCAL_SETUP_ZKSYNC_NETWORK } from '../constants'; export type StandaloneOptions = @@ -28,14 +27,14 @@ export type CustomDataOptions = From 2479f8731e65923fde00346fb595bd5525401c6e Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Tue, 3 Sep 2024 15:59:53 +0200 Subject: [PATCH 14/20] feat: bump openzeppelin contracts to v5 --- examples/basic-example/package.json | 4 +- examples/node-example/package.json | 4 +- .../noninline-libraries-example/package.json | 4 +- .../contracts/BoxUups.sol | 2 +- examples/upgradable-example-l1/package.json | 4 +- .../scripts/deploy-box-uups.ts | 2 +- .../scripts/upgrade-box-uups.ts | 2 +- .../upgradable-example/contracts/BoxUups.sol | 2 +- examples/upgradable-example/package.json | 6 +- .../scripts/deploy-box-uups-factory.ts | 2 +- .../scripts/deploy-box-uups.ts | 2 +- .../scripts/upgrade-box-uups-factory.ts | 2 +- .../scripts/upgrade-box-uups.ts | 2 +- .../hardhat-zksync-upgradable/package.json | 10 +- .../hardhat-zksync-upgradable/src/admin.ts | 62 +-- .../src/core/validate.ts | 18 +- .../src/extension-generator.ts | 5 +- .../estimate-gas-beacon-proxy.ts | 11 +- .../src/gas-estimation/estimate-gas-beacon.ts | 21 +- .../src/gas-estimation/estimate-gas-proxy.ts | 35 +- .../hardhat-zksync-upgradable/src/index.ts | 11 + .../src/interfaces.ts | 5 +- .../defender-v1/propose-upgrade.ts | 103 ---- .../defender-v1/verify-deployment.ts | 100 ---- .../extension-generator.ts | 4 - .../interfaces.ts | 25 +- .../hardhat-zksync-upgradable/src/plugin.ts | 8 + .../proxy-deployment/deploy-beacon-proxy.ts | 18 +- .../src/proxy-deployment/deploy-beacon.ts | 20 +- .../src/proxy-deployment/deploy-impl.ts | 1 - .../proxy-deployment/deploy-proxy-admin.ts | 53 -- .../src/proxy-deployment/deploy-proxy.ts | 72 +-- .../src/proxy-upgrade/upgrade-beacon.ts | 17 +- .../src/proxy-upgrade/upgrade-proxy.ts | 74 ++- .../hardhat-zksync-upgradable/src/utils.ts | 2 +- .../src/utils/attach-abi.ts | 35 ++ .../src/utils/factories.ts | 120 ++++ .../src/utils/options.ts | 8 +- .../src/validations/validate-impl.ts | 24 +- .../contracts/BoxUups.sol | 2 +- .../uups-e2e/contracts/BoxUups.sol | 2 +- .../contracts/BoxUupsMissingUpgradeTo.sol | 2 +- .../uups-e2e/contracts/BoxUupsPublic.sol | 2 +- .../hardhat-zksync-upgradable/test/tests.ts | 101 ++-- packages/hardhat-zksync/package.json | 6 +- pnpm-lock.yaml | 513 +++++------------- 46 files changed, 526 insertions(+), 1002 deletions(-) delete mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts delete mode 100644 packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts delete mode 100644 packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts create mode 100644 packages/hardhat-zksync-upgradable/src/utils/attach-abi.ts create mode 100644 packages/hardhat-zksync-upgradable/src/utils/factories.ts diff --git a/examples/basic-example/package.json b/examples/basic-example/package.json index e424ebbff..0eb0e33c8 100644 --- a/examples/basic-example/package.json +++ b/examples/basic-example/package.json @@ -36,8 +36,8 @@ "ethers": "^6.12.2", "zksync-ethers": "^6.8.0", "@matterlabs/zksync-contracts": "^0.6.1", - "@openzeppelin/contracts": "^4.9.2", - "@openzeppelin/contracts-upgradeable": "^4.9.2" + "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2" }, "prettier": { "tabWidth": 4, diff --git a/examples/node-example/package.json b/examples/node-example/package.json index ae28122a2..974a7b471 100644 --- a/examples/node-example/package.json +++ b/examples/node-example/package.json @@ -42,8 +42,8 @@ "ethers": "^6.12.2", "zksync-ethers": "^6.8.0", "@matterlabs/zksync-contracts": "^0.6.1", - "@openzeppelin/contracts": "^4.9.2", - "@openzeppelin/contracts-upgradeable": "^4.9.2" + "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2" }, "prettier": { "tabWidth": 4, diff --git a/examples/noninline-libraries-example/package.json b/examples/noninline-libraries-example/package.json index 008eab265..540c3af50 100644 --- a/examples/noninline-libraries-example/package.json +++ b/examples/noninline-libraries-example/package.json @@ -36,8 +36,8 @@ "ethers": "^6.12.2", "zksync-ethers": "^6.8.0", "@matterlabs/zksync-contracts": "^0.6.1", - "@openzeppelin/contracts": "^4.9.2", - "@openzeppelin/contracts-upgradeable": "^4.9.2" + "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2" }, "prettier": { "tabWidth": 4, diff --git a/examples/upgradable-example-l1/contracts/BoxUups.sol b/examples/upgradable-example-l1/contracts/BoxUups.sol index 0b3345dd7..0bd67e5bb 100644 --- a/examples/upgradable-example-l1/contracts/BoxUups.sol +++ b/examples/upgradable-example-l1/contracts/BoxUups.sol @@ -11,7 +11,7 @@ contract BoxUups is Initializable, UUPSUpgradeable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } diff --git a/examples/upgradable-example-l1/package.json b/examples/upgradable-example-l1/package.json index f4252c0f7..6fbd4d022 100644 --- a/examples/upgradable-example-l1/package.json +++ b/examples/upgradable-example-l1/package.json @@ -15,7 +15,7 @@ "clean": "rimraf dist" }, "devDependencies": { - "@openzeppelin/contracts": "^4.9.2", + "@openzeppelin/contracts": "^5.0.2", "@types/node": "^18.11.17", "@typescript-eslint/eslint-plugin": "6.13.1", "@typescript-eslint/parser": "6.13.1", @@ -36,7 +36,7 @@ "@matterlabs/hardhat-zksync-upgradable": "workspace:^", "@matterlabs/hardhat-zksync-verify": "workspace:^", "@nomicfoundation/hardhat-ethers": "3.0.6", - "@openzeppelin/contracts-upgradeable": "^4.9.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2", "chalk": "^4.1.2", "ethers": "^6.12.2", "hardhat": "^2.22.5", diff --git a/examples/upgradable-example-l1/scripts/deploy-box-uups.ts b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts index e660872e4..49fc4dd15 100644 --- a/examples/upgradable-example-l1/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts @@ -2,7 +2,7 @@ import * as hre from 'hardhat'; async function main() { const Box = await hre.ethers.getContractFactory("BoxUups"); - const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize'}); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); await box.waitForDeployment() console.info("Box deployed address: " + await box.getAddress()) } diff --git a/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts index 902084bc1..d107ff162 100644 --- a/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts @@ -2,7 +2,7 @@ import * as hre from 'hardhat'; async function main() { const Box = await hre.ethers.getContractFactory("BoxUups"); - const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize'}); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); await box.waitForDeployment() console.info("Box deployed address: " + await box.getAddress()) diff --git a/examples/upgradable-example/contracts/BoxUups.sol b/examples/upgradable-example/contracts/BoxUups.sol index 0b3345dd7..0bd67e5bb 100644 --- a/examples/upgradable-example/contracts/BoxUups.sol +++ b/examples/upgradable-example/contracts/BoxUups.sol @@ -11,7 +11,7 @@ contract BoxUups is Initializable, UUPSUpgradeable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } diff --git a/examples/upgradable-example/package.json b/examples/upgradable-example/package.json index 746a5f897..389ed061a 100644 --- a/examples/upgradable-example/package.json +++ b/examples/upgradable-example/package.json @@ -15,7 +15,7 @@ "clean": "rimraf dist" }, "devDependencies": { - "@openzeppelin/contracts": "^4.9.2", + "@openzeppelin/contracts": "^5.0.2", "@types/node": "^18.11.17", "@typescript-eslint/eslint-plugin": "6.13.1", "@typescript-eslint/parser": "6.13.1", @@ -36,8 +36,8 @@ "@matterlabs/hardhat-zksync-upgradable": "workspace:^", "@matterlabs/hardhat-zksync-verify": "workspace:^", "@nomicfoundation/hardhat-ethers": "3.0.6", - "@openzeppelin/contracts-upgradeable": "^4.9.2", - "@openzeppelin/hardhat-upgrades": "^2.5.1", + "@openzeppelin/contracts-upgradeable": "^5.0.2", + "@openzeppelin/hardhat-upgrades": "^3.2.1", "chalk": "^4.1.2", "ethers": "^6.12.2", "hardhat": "^2.22.5", diff --git a/examples/upgradable-example/scripts/deploy-box-uups-factory.ts b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts index 60e83b649..14d99405b 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups-factory.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts @@ -14,7 +14,7 @@ async function main() { const deployer = new Deployer(hre, zkWallet); const boxFactory = await hre.zksyncEthers.getContractFactory('BoxUups', deployer.zkWallet); - const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/deploy-box-uups.ts b/examples/upgradable-example/scripts/deploy-box-uups.ts index c7c70881d..a1d50cc5c 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups.ts @@ -14,7 +14,7 @@ async function main() { const deployer = new Deployer(hre, zkWallet); const contract = await deployer.loadArtifact(contractName); - const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment'] }); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts b/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts index 79f3a9522..3d014514d 100644 --- a/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts +++ b/examples/upgradable-example/scripts/upgrade-box-uups-factory.ts @@ -13,7 +13,7 @@ async function main() { const contractName = 'BoxUups'; const boxFactory = await hre.zksyncEthers.getContractFactory(contractName, deployer.zkWallet); - const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment'] }); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/upgrade-box-uups.ts b/examples/upgradable-example/scripts/upgrade-box-uups.ts index c259ace14..d7ddc709e 100644 --- a/examples/upgradable-example/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example/scripts/upgrade-box-uups.ts @@ -13,7 +13,7 @@ async function main() { const contractName = 'BoxUups'; const contract = await deployer.loadArtifact(contractName); - const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment'] }); await box.waitForDeployment(); diff --git a/packages/hardhat-zksync-upgradable/package.json b/packages/hardhat-zksync-upgradable/package.json index 79ca7be1e..7fb3242d5 100644 --- a/packages/hardhat-zksync-upgradable/package.json +++ b/packages/hardhat-zksync-upgradable/package.json @@ -35,11 +35,13 @@ "dependencies": { "@matterlabs/hardhat-zksync-deploy": "workspace:^", "@matterlabs/hardhat-zksync-solc": "workspace:^", - "@openzeppelin/contracts-hardhat-zksync-upgradable": "npm:@openzeppelin/contracts@^4.9.2", - "@openzeppelin/hardhat-upgrades": "~2.5.1", - "@openzeppelin/upgrades-core": "^1.31.3", + "@openzeppelin/contracts-hardhat-zksync-upgradable": "npm:@openzeppelin/contracts@^5.0.2", + "@openzeppelin/hardhat-upgrades": "^3.2.1", + "@openzeppelin/upgrades-core": "^1.37.0", "@nomicfoundation/hardhat-ethers": "^3.0.6", - "@openzeppelin/defender-admin-client": "^1.52.0", + "@openzeppelin/defender-sdk-base-client": "^1.10.0", + "@openzeppelin/defender-sdk-deploy-client": "^1.10.0", + "@openzeppelin/defender-sdk-network-client": "^1.10.0", "chalk": "^4.1.2", "compare-versions": "^6.1.0", "ethereumjs-util": "^7.1.5", diff --git a/packages/hardhat-zksync-upgradable/src/admin.ts b/packages/hardhat-zksync-upgradable/src/admin.ts index 6bbec59da..c2636475c 100644 --- a/packages/hardhat-zksync-upgradable/src/admin.ts +++ b/packages/hardhat-zksync-upgradable/src/admin.ts @@ -1,62 +1,28 @@ -import chalk from 'chalk'; -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import { getAdminAddress } from '@openzeppelin/upgrades-core'; -import { Wallet, Contract } from 'zksync-ethers'; -import { Manifest } from './core/manifest'; -import { getAdminFactory } from './proxy-deployment/deploy-proxy-admin'; -import { ZkSyncUpgradablePluginError } from './errors'; +import { Wallet } from 'zksync-ethers'; +import { attachProxyAdminV4 } from './utils/attach-abi'; export type ChangeAdminFunction = (proxyAddress: string, newAdmin: string, wallet: Wallet) => Promise; -export type TransferProxyAdminOwnershipFunction = (newOwner: string, wallet: Wallet) => Promise; -export type GetInstanceFunction = (wallet: Wallet) => Promise; +export type TransferProxyAdminOwnershipFunction = ( + proxyAddress: string, + newOwner: string, + wallet: Wallet, +) => Promise; -export function makeChangeProxyAdmin(hre: HardhatRuntimeEnvironment): ChangeAdminFunction { +export function makeChangeProxyAdmin(): ChangeAdminFunction { return async function changeProxyAdmin(proxyAddress, newAdmin, wallet: Wallet) { - const proxyAdminManifest = await getManifestAdmin(hre, wallet); - const proxyAdminAddress = await getAdminAddress(wallet.provider, proxyAddress); - if ((await proxyAdminManifest.getAddress()) !== proxyAdminAddress) { - throw new ZkSyncUpgradablePluginError('Proxy admin is not the one registered in the network manifest'); - } else if ((await proxyAdminManifest.getAddress()) !== newAdmin) { - await proxyAdminManifest.changeProxyAdmin(proxyAddress, newAdmin); - } + const admin = await attachProxyAdminV4(proxyAdminAddress, wallet); + await admin.changeProxyAdmin(proxyAddress, newAdmin); }; } -export function makeTransferProxyAdminOwnership(hre: HardhatRuntimeEnvironment): TransferProxyAdminOwnershipFunction { - return async function transferProxyAdminOwnership(newOwner, wallet: Wallet) { - const admin = await getManifestAdmin(hre, wallet); +export function makeTransferProxyAdminOwnership(): TransferProxyAdminOwnershipFunction { + return async function transferProxyAdminOwnership(proxyAddress: string, newOwner, wallet: Wallet) { + const proxyAdminAddress = await getAdminAddress(wallet.provider, proxyAddress); + const admin = await attachProxyAdminV4(proxyAdminAddress, wallet); await admin.transferOwnership(newOwner); - - const manifest = await Manifest.forNetwork(wallet.provider); - const { proxies } = await manifest.read(); - for (const { address, kind } of proxies) { - if ((await admin.getAddress()) === (await getAdminAddress(wallet.provider, address))) { - console.info(chalk.green(`${address} (${kind}) proxy ownership transfered through admin proxy`)); - } else { - console.info(chalk.red(`${address} (${kind}) proxy ownership not affected by admin proxy`)); - } - } - }; -} - -export function makeGetInstanceFunction(hre: HardhatRuntimeEnvironment): GetInstanceFunction { - return async function getInstance(wallet: Wallet) { - return await getManifestAdmin(hre, wallet); }; } - -export async function getManifestAdmin(hre: HardhatRuntimeEnvironment, wallet: Wallet): Promise { - const manifest = await Manifest.forNetwork(wallet.provider); - const manifestAdmin = await manifest.getAdmin(); - const proxyAdminAddress = manifestAdmin?.address; - - if (proxyAdminAddress === undefined) { - throw new ZkSyncUpgradablePluginError('No ProxyAdmin was found in the network manifest'); - } - - const adminFactory = await getAdminFactory(hre, wallet); - return adminFactory.attach(proxyAdminAddress); -} diff --git a/packages/hardhat-zksync-upgradable/src/core/validate.ts b/packages/hardhat-zksync-upgradable/src/core/validate.ts index 619fef4ee..d01c9415c 100644 --- a/packages/hardhat-zksync-upgradable/src/core/validate.ts +++ b/packages/hardhat-zksync-upgradable/src/core/validate.ts @@ -253,25 +253,25 @@ function* getStateVariableErrors( ): Generator { for (const varDecl of contractDef.nodes) { if (isNodeType('VariableDeclaration', varDecl)) { - if (!varDecl.constant && !isNullish(varDecl.value)) { + if (varDecl.mutability === 'immutable') { if ( - !skipCheck('state-variable-assignment', contractDef) && - !skipCheck('state-variable-assignment', varDecl) + !skipCheck('state-variable-immutable', contractDef) && + !skipCheck('state-variable-immutable', varDecl) ) { yield { - kind: 'state-variable-assignment', + kind: 'state-variable-immutable', name: varDecl.name, src: decodeSrc(varDecl), }; } - } - if (varDecl.mutability === 'immutable') { + } else if (!varDecl.constant && !isNullish(varDecl.value)) { + // Assignments are only a concern for non-immutable variables if ( - !skipCheck('state-variable-immutable', contractDef) && - !skipCheck('state-variable-immutable', varDecl) + !skipCheck('state-variable-assignment', contractDef) && + !skipCheck('state-variable-assignment', varDecl) ) { yield { - kind: 'state-variable-immutable', + kind: 'state-variable-assignment', name: varDecl.name, src: decodeSrc(varDecl), }; diff --git a/packages/hardhat-zksync-upgradable/src/extension-generator.ts b/packages/hardhat-zksync-upgradable/src/extension-generator.ts index 19a1097e5..c8a9c25a4 100644 --- a/packages/hardhat-zksync-upgradable/src/extension-generator.ts +++ b/packages/hardhat-zksync-upgradable/src/extension-generator.ts @@ -20,11 +20,10 @@ export class ZkSyncGenerator implements Generator { const { makeDeployBeacon } = require('./proxy-deployment/deploy-beacon'); const { makeDeployBeaconProxy } = require('./proxy-deployment/deploy-beacon-proxy'); const { makeUpgradeBeacon } = require('./proxy-upgrade/upgrade-beacon'); - const { makeDeployProxyAdmin } = require('./proxy-deployment/deploy-proxy-admin'); const { makeEstimateGasProxy } = require('./gas-estimation/estimate-gas-proxy'); const { makeEstimateGasBeacon } = require('./gas-estimation/estimate-gas-beacon'); const { makeEstimateGasBeaconProxy } = require('./gas-estimation/estimate-gas-beacon-proxy'); - const { makeGetInstanceFunction, makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); + const { makeChangeProxyAdmin, makeTransferProxyAdminOwnership } = require('./admin'); return { deployProxy: wrapMakeFunction(this._hre, makeDeployProxy(this._hre)), upgradeProxy: wrapMakeFunction(this._hre, makeUpgradeProxy(this._hre)), @@ -32,9 +31,7 @@ export class ZkSyncGenerator implements Generator { deployBeacon: wrapMakeFunction(this._hre, makeDeployBeacon(this._hre)), deployBeaconProxy: wrapMakeFunction(this._hre, makeDeployBeaconProxy(this._hre)), upgradeBeacon: wrapMakeFunction(this._hre, makeUpgradeBeacon(this._hre)), - deployProxyAdmin: wrapMakeFunction(this._hre, makeDeployProxyAdmin(this._hre)), admin: { - getInstance: wrapMakeFunction(this._hre, makeGetInstanceFunction(this._hre)), changeProxyAdmin: wrapMakeFunction(this._hre, makeChangeProxyAdmin(this._hre)), transferProxyAdminOwnership: wrapMakeFunction(this._hre, makeTransferProxyAdminOwnership(this._hre)), }, diff --git a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon-proxy.ts index 400ad337b..fdd1b81f3 100644 --- a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon-proxy.ts @@ -1,14 +1,11 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import chalk from 'chalk'; -import assert from 'assert'; -import path from 'path'; import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; import { DeployProxyOptions } from '../utils/options'; import { ZkSyncUpgradablePluginError } from '../errors'; import { convertGasPriceToEth } from '../utils/utils-general'; -import { BEACON_PROXY_JSON } from '../constants'; -import { getUpgradableContracts } from '../utils'; +import { getBeaconProxyArtifact } from '../utils/factories'; import { getMockedBeaconData } from './estimate-gas-beacon'; export type EstimateBeaconGasFunction = ( @@ -27,11 +24,7 @@ export function makeEstimateGasBeaconProxy(hre: HardhatRuntimeEnvironment): Esti ) { const { mockedBeaconAddress, data } = await getMockedBeaconData(deployer, hre, args, opts); - const beaconProxyPath = (await hre.artifacts.getArtifactPaths()).find((artifactPath) => - artifactPath.includes(path.sep + getUpgradableContracts().BeaconProxy + path.sep + BEACON_PROXY_JSON), - ); - assert(beaconProxyPath, 'Beacon proxy artifact not found'); - const beaconProxyContract = await import(beaconProxyPath); + const beaconProxyContract = await getBeaconProxyArtifact(hre); try { const beaconProxyGasCost = await deployer.estimateDeployFee(beaconProxyContract, [ diff --git a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon.ts b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon.ts index 791d32e26..9c2525d0c 100644 --- a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-beacon.ts @@ -1,18 +1,15 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import * as ethers from 'ethers'; import chalk from 'chalk'; -import assert from 'assert'; -import path from 'path'; + import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; import { DeployProxyOptions } from '../utils/options'; import { ZkSyncUpgradablePluginError } from '../errors'; import { convertGasPriceToEth, getInitializerData } from '../utils/utils-general'; -import { UPGRADABLE_BEACON_JSON } from '../constants'; -import { getAdminArtifact } from '../proxy-deployment/deploy-proxy-admin'; import { getChainId } from '../core/provider'; -import { getUpgradableContracts } from '../utils'; +import { getProxyAdminArtifact, getUpgradableBeaconArtifact } from '../utils/factories'; export type EstimateGasFunction = ( deployer: Deployer, @@ -35,7 +32,7 @@ export async function getMockedBeaconData( } const mockedBeaconAddress = await getDeployedBeaconAddress(deployer); - const mockArtifact = await getAdminArtifact(hre); + const mockArtifact = await getProxyAdminArtifact(hre); const data = getInitializerData(new ethers.Interface(mockArtifact.abi), args, opts.initializer); return { mockedBeaconAddress, data }; @@ -74,15 +71,13 @@ export function makeEstimateGasBeacon(hre: HardhatRuntimeEnvironment): EstimateG ), ); } - - const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), - ); - assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); - const upgradeableBeaconContract = await import(upgradableBeaconPath); + const upgradeableBeaconContract = await getUpgradableBeaconArtifact(hre); try { - beaconGasCost = await deployer.estimateDeployFee(upgradeableBeaconContract, [mockedBeaconAddress]); + beaconGasCost = await deployer.estimateDeployFee(upgradeableBeaconContract, [ + mockedBeaconAddress, + opts.initialOwner ?? deployer.zkWallet.address, + ]); if (!quiet) { console.info( chalk.cyan( diff --git a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-proxy.ts b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-proxy.ts index 61e22de92..ae7485527 100644 --- a/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/gas-estimation/estimate-gas-proxy.ts @@ -1,8 +1,7 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import * as ethers from 'ethers'; import chalk from 'chalk'; -import assert from 'assert'; -import path from 'path'; + import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import { Deployer } from '@matterlabs/hardhat-zksync-deploy'; @@ -10,9 +9,7 @@ import { ZkSyncUpgradablePluginError } from '../errors'; import { DeployProxyOptions } from '../utils/options'; import { convertGasPriceToEth, getInitializerData } from '../utils/utils-general'; import { getChainId } from '../core/provider'; -import { ERC1967_PROXY_JSON, TUP_JSON } from '../constants'; -import { getAdminArtifact } from '../proxy-deployment/deploy-proxy-admin'; -import { getUpgradableContracts } from '../utils'; +import { getProxyAdminArtifact, getProxyArtifact, getTransparentUpgradeableProxyArtifact } from '../utils/factories'; export type EstimateProxyGasFunction = ( deployer: Deployer, @@ -36,7 +33,7 @@ export function makeEstimateGasProxy(hre: HardhatRuntimeEnvironment): EstimatePr ): Promise { let totalGasCost: bigint; - const mockArtifact = await getAdminArtifact(hre); + const mockArtifact = await getProxyAdminArtifact(hre); const kind = opts.kind; const chainId = await getChainId(deployer.zkWallet.provider); @@ -45,6 +42,8 @@ export function makeEstimateGasProxy(hre: HardhatRuntimeEnvironment): EstimatePr throw new ZkSyncUpgradablePluginError(`Chain id ${chainId} is not supported!`); } + const initialOwner = opts.initialOwner ?? deployer.zkWallet.address; + const mockImplAddress = await getProxyAdminContractAddress(); const data = getInitializerData(new ethers.Interface(mockArtifact.abi), args, opts.initializer); @@ -77,6 +76,7 @@ export function makeEstimateGasProxy(hre: HardhatRuntimeEnvironment): EstimatePr deployer, mockImplAddress, data, + initialOwner, quiet, ); totalGasCost = implGasCost + adminGasCost + proxyGasCost; @@ -109,11 +109,7 @@ async function estimateGasUUPS( data: string, quiet: boolean = false, ): Promise { - const ERC1967ProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ERC1967Proxy + path.sep + ERC1967_PROXY_JSON), - ); - assert(ERC1967ProxyPath, 'ERC1967Proxy artifact not found'); - const proxyContract = await import(ERC1967ProxyPath); + const proxyContract = await getProxyArtifact(hre); try { const uupsGasCost: bigint = await deployer.estimateDeployFee(proxyContract, [mockImplAddress, data]); @@ -137,10 +133,11 @@ async function estimateGasTransparent( deployer: Deployer, mockImplAddress: string, data: string, + initialOwner?: string, quiet: boolean = false, ): Promise { - const adminArtifact = await getAdminArtifact(hre); - const adminGasCost = await deployer.estimateDeployFee(adminArtifact, []); + const adminArtifact = await getProxyAdminArtifact(hre); + const adminGasCost = await deployer.estimateDeployFee(adminArtifact, [initialOwner ?? deployer.zkWallet.address]); let proxyGasCost; if (!quiet) { console.info( @@ -152,14 +149,14 @@ async function estimateGasTransparent( ); } - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + TUP_JSON), - ); - assert(TUPPath, 'TUP artifact not found'); - const TUPContract = await import(TUPPath); + const TUPContract = await getTransparentUpgradeableProxyArtifact(hre); try { - proxyGasCost = await deployer.estimateDeployFee(TUPContract, [mockImplAddress, mockImplAddress, data]); + proxyGasCost = await deployer.estimateDeployFee(TUPContract, [ + mockImplAddress, + initialOwner ?? deployer.zkWallet.address, + data, + ]); if (!quiet) { console.info( chalk.cyan( diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index 87c42d979..ff7b6fb3d 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -9,6 +9,7 @@ import { TASK_COMPILE_SOLIDITY_COMPILE } from 'hardhat/builtin-tasks/task-names' import { RunCompilerArgs } from './interfaces'; import { isFullZkSolcOutput } from './utils/utils-general'; import { validate } from './core/validate'; + import { TASK_DEPLOY_ZKSYNC_BEACON, TASK_DEPLOY_ZKSYNC_PROXY, @@ -41,6 +42,7 @@ task(TASK_DEPLOY_ZKSYNC_BEACON, 'Runs the beaccon deploy for ZKsync network') .addOptionalParam('deploymentTypeProxy', 'Type of deployment for proxy', undefined) .addOptionalParam('saltImpl', 'Salt for implementation deployment', undefined) .addOptionalParam('saltProxy', 'Salt for proxy deployment', undefined) + .addOptionalParam('initialOwner', 'Initial owner of the proxy', undefined) .addFlag('noCompile', 'No compile flag') .setAction(deployZkSyncBeacon); @@ -62,6 +64,11 @@ task(TASK_DEPLOY_ZKSYNC_PROXY, 'Deploy proxy for ZKsync network') .addOptionalParam('deploymentTypeProxy', 'Type of deployment for proxy', undefined) .addOptionalParam('saltImpl', 'Salt for implementation deployment', undefined) .addOptionalParam('saltProxy', 'Salt for proxy deployment', undefined) + .addOptionalParam('initialOwner', 'Initial owner of the proxy', undefined) + .addFlag( + 'unsafeStateVariableAssignment', + 'Allow unsafe state-variable-assignment. This flag is mandatory for uups proxy deployment.', + ) .addFlag('noCompile', 'No compile flag') .setAction(deployZkSyncProxy); @@ -78,6 +85,10 @@ task(TASK_UPGRADE_ZKSYNC_PROXY, 'Runs the proxy upgrade for ZKsync network') .addParam('proxyAddress', 'Proxy address of the deployed contract', '') .addOptionalParam('deploymentType', 'Type of deployment', undefined) .addOptionalParam('salt', 'Salt for deployment', undefined) + .addFlag( + 'unsafeStateVariableAssignment', + 'Allow unsafe state-variable-assignment. This flag is mandatory for uups proxy upgrade.', + ) .addFlag('noCompile', 'No compile flag') .setAction(upgradeZkSyncProxy); diff --git a/packages/hardhat-zksync-upgradable/src/interfaces.ts b/packages/hardhat-zksync-upgradable/src/interfaces.ts index 2f6ae873c..30a8c4dca 100644 --- a/packages/hardhat-zksync-upgradable/src/interfaces.ts +++ b/packages/hardhat-zksync-upgradable/src/interfaces.ts @@ -13,9 +13,8 @@ import { DeployBeaconArtifact, DeployBeaconFactory } from './proxy-deployment/de import { DeployBeaconProxyArtifact, DeployBeaconProxyFactory } from './proxy-deployment/deploy-beacon-proxy'; import { EstimateProxyGasFunction } from './gas-estimation/estimate-gas-proxy'; import { EstimateBeaconGasFunction } from './gas-estimation/estimate-gas-beacon-proxy'; -import { ChangeAdminFunction, GetInstanceFunction, TransferProxyAdminOwnershipFunction } from './admin'; +import { ChangeAdminFunction, TransferProxyAdminOwnershipFunction } from './admin'; import { ValidateImplementationOptions } from './utils/options'; -import { DeployAdminFunction } from './proxy-deployment/deploy-proxy-admin'; import { UndefinedFunctionType } from './utils'; export type ValidateImplementationFunction = ( @@ -30,9 +29,7 @@ export interface HardhatZksyncUpgrades { deployBeacon: DeployBeaconArtifact & DeployBeaconFactory; deployBeaconProxy: DeployBeaconProxyFactory & DeployBeaconProxyArtifact; upgradeBeacon: UpgradeBeaconFactory & UpgradeBeaconArtifact; - deployProxyAdmin: DeployAdminFunction; admin: { - getInstance: GetInstanceFunction; changeProxyAdmin: ChangeAdminFunction; transferProxyAdminOwnership: TransferProxyAdminOwnershipFunction; }; diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts deleted file mode 100644 index 6ab725051..000000000 --- a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { - getImplementationAddress, - isBeaconProxy, - isTransparentOrUUPSProxy, - isTransparentProxy, -} from '@openzeppelin/upgrades-core'; -import { ProposalResponse, CreateProposalRequest } from '@openzeppelin/defender-admin-client'; -import { ContractFactory, getCreateAddress, ethers } from 'ethers'; -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { getAdminClient, getNetwork } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/utils'; -import { UpgradeOptions } from '@openzeppelin/hardhat-upgrades/dist/utils/options'; -import type { VerificationResponse } from './verify-deployment'; - -export interface ExtendedProposalResponse extends ProposalResponse { - txResponse?: ethers.TransactionResponse; - verificationResponse?: VerificationResponse; -} - -export type ProposeUpgradeFunction = ( - proxyAddress: string, - contractNameOrImplFactory: string | ContractFactory, - opts?: ProposalOptions, -) => Promise; - -export interface ProposalOptions extends UpgradeOptions { - title?: string; - description?: string; - proxyAdmin?: string; - multisig?: string; - multisigType?: CreateProposalRequest['viaType']; - bytecodeVerificationReferenceUrl?: string; -} - -export function makeProposeUpgrade(hre: HardhatRuntimeEnvironment): ProposeUpgradeFunction { - return async function proposeUpgrade(proxyAddress, contractNameOrImplFactory, opts = {}) { - const client = getAdminClient(hre); - const network = await getNetwork(hre); - - const { title, description, proxyAdmin, multisig, multisigType, ...moreOpts } = opts; - - if (await isBeaconProxy(hre.network.provider, proxyAddress)) { - throw new Error(`Beacon proxy is not currently supported with defender.proposeUpgrade()`); - } else if ( - !multisig && - (await isTransparentOrUUPSProxy(hre.network.provider, proxyAddress)) && - !(await isTransparentProxy(hre.network.provider, proxyAddress)) - ) { - throw new Error(`Multisig address is a required property for UUPS proxies`); - } else { - // try getting the implementation address so that it will give an error if it's not a transparent/uups proxy - await getImplementationAddress(hre.network.provider, proxyAddress); - } - - const implFactory = - typeof contractNameOrImplFactory === 'string' - ? await hre.ethers.getContractFactory(contractNameOrImplFactory) - : contractNameOrImplFactory; - const contractName = typeof contractNameOrImplFactory === 'string' ? contractNameOrImplFactory : undefined; - const contract = { address: proxyAddress, network, abi: implFactory.interface.formatJson() }; - - const prepareUpgradeResult = await hre.upgrades.prepareUpgrade(proxyAddress, implFactory, { - getTxResponse: true, - ...moreOpts, - }); - - let txResponse; - let newImplementation; - - if (typeof prepareUpgradeResult === 'string') { - newImplementation = prepareUpgradeResult; - } else { - txResponse = prepareUpgradeResult; - newImplementation = getCreateAddress(txResponse); - } - - const verificationResponse = - contractName && opts.bytecodeVerificationReferenceUrl - ? await hre.defender.verifyDeployment( - newImplementation, - contractName, - opts.bytecodeVerificationReferenceUrl, - ) - : undefined; - - const proposalResponse = await client.proposeUpgrade( - { - newImplementation, - title, - description, - proxyAdmin, - via: multisig, - viaType: multisigType, - }, - contract, - ); - - return { - ...proposalResponse, - txResponse, - verificationResponse, - }; - }; -} diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts deleted file mode 100644 index 64a48b5dc..000000000 --- a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/defender-v1/verify-deployment.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { AdminClient, VerificationRequest } from '@openzeppelin/defender-admin-client'; -import { Artifact, BuildInfo, CompilerOutputBytecode, HardhatRuntimeEnvironment } from 'hardhat/types'; -import { getAdminClient, getNetwork } from '@openzeppelin/hardhat-upgrades/dist/defender-v1/utils'; -import { sha256FromString } from 'ethereumjs-util'; - -export type VerificationResponse = Awaited>; - -type ExtendedArtifact = Artifact & { immutableReferences: CompilerOutputBytecode['immutableReferences'] }; - -export type VerifyDeployFunction = ( - address: string, - contractName: string, - referenceUrl: string, -) => Promise; - -export type VerifyDeployWithUploadedArtifactFunction = ( - address: string, - contractName: string, - artifactUri: string, -) => Promise; - -export type GetVerifyDeployArtifactFunction = (contractName: string) => Promise; - -export type GetVerifyDeployBuildInfoFunction = (contractName: string) => Promise; - -export type GetBytecodeDigestFunction = (contractName: string) => Promise; - -export function makeVerifyDeploy(hre: HardhatRuntimeEnvironment): VerifyDeployFunction { - return async function verifyDeploy(address, contractName, referenceUri) { - const client = getAdminClient(hre); - const contractNetwork = await getNetwork(hre); - const artifact = await getExtendedArtifact(hre, contractName); - - const request: VerificationRequest = { - contractAddress: address, - contractName: artifact.contractName, - solidityFilePath: artifact.sourceName, - contractNetwork, - artifactPayload: JSON.stringify(artifact), - referenceUri, - }; - - return client.verifyDeployment(request); - }; -} - -export function makeVerifyDeployWithUploadedArtifact( - hre: HardhatRuntimeEnvironment, -): VerifyDeployWithUploadedArtifactFunction { - return async function verifyDeploy(address, contractName, artifactUri) { - const client = getAdminClient(hre); - const contractNetwork = await getNetwork(hre); - const artifact = await hre.artifacts.readArtifact(contractName); - - const request: VerificationRequest = { - contractAddress: address, - contractName: artifact.contractName, - solidityFilePath: artifact.sourceName, - artifactUri, - contractNetwork, - }; - - return client.verifyDeployment(request); - }; -} - -export function makeGetVerifyDeployArtifact(hre: HardhatRuntimeEnvironment): GetVerifyDeployArtifactFunction { - return async function getVerifyDeployArtifact(contractName: string): Promise { - return getExtendedArtifact(hre, contractName); - }; -} - -export function makeGetVerifyDeployBuildInfo(hre: HardhatRuntimeEnvironment): GetVerifyDeployBuildInfoFunction { - return async function getVerifyDeployBuildInfo(contractName: string): Promise { - const artifact = await hre.artifacts.readArtifact(contractName); - const fqn = `${artifact.sourceName}:${artifact.contractName}`; - const buildInfo = await hre.artifacts.getBuildInfo(fqn); - if (!buildInfo) { - throw new Error(`Build info for ${fqn} not found`); - } - return buildInfo; - }; -} - -export function makeGetBytecodeDigest(hre: HardhatRuntimeEnvironment) { - return async function getBytecodeDigest(contractName: string): Promise { - const artifact = await hre.artifacts.readArtifact(contractName); - const bytecode = artifact.deployedBytecode; - return sha256FromString(bytecode).toString('hex'); - }; -} - -async function getExtendedArtifact(hre: HardhatRuntimeEnvironment, contractName: string): Promise { - const artifact = await hre.artifacts.readArtifact(contractName); - const fqn = `${artifact.sourceName}:${artifact.contractName}`; - const buildInfo = await hre.artifacts.getBuildInfo(fqn); - const contractBuildInfo = buildInfo?.output.contracts[artifact.sourceName][artifact.contractName]; - const immutableReferences = contractBuildInfo?.evm.deployedBytecode.immutableReferences ?? {}; - return { ...artifact, immutableReferences }; -} diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts index 8d4dd3350..0df90662a 100644 --- a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/extension-generator.ts @@ -34,11 +34,9 @@ export class OpenzeppelinGenerator implements Generator { const { makeDeployBeaconProxy } = require('@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'); const { makeUpgradeBeacon } = require('@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'); const { makeForceImport } = require('@openzeppelin/hardhat-upgrades/dist/force-import'); - const { makeDeployProxyAdmin } = require('@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'); const { makeChangeProxyAdmin, makeTransferProxyAdminOwnership, - makeGetInstanceFunction, } = require('@openzeppelin/hardhat-upgrades/dist/admin'); return { @@ -51,11 +49,9 @@ export class OpenzeppelinGenerator implements Generator { prepareUpgrade: makePrepareUpgrade(this._hre, defender), deployBeacon: makeDeployBeacon(this._hre, defender), // block on defender deployBeaconProxy: makeDeployBeaconProxy(this._hre, defender), - deployProxyAdmin: makeDeployProxyAdmin(this._hre, defender), upgradeBeacon: makeUpgradeBeacon(this._hre, defender), // block on defender forceImport: makeForceImport(this._hre), admin: { - getInstance: makeGetInstanceFunction(this._hre, defender), // block on defender changeProxyAdmin: makeChangeProxyAdmin(this._hre, defender), // block on defender transferProxyAdminOwnership: makeTransferProxyAdminOwnership(this._hre, defender), // block on defender }, diff --git a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts index f975ac075..074e0de13 100644 --- a/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts +++ b/packages/hardhat-zksync-upgradable/src/openzeppelin-hardhat-upgrades/interfaces.ts @@ -6,12 +6,10 @@ import { UpgradeFunction as UpgradeFunctionOZ } from '@openzeppelin/hardhat-upgr import { DeployBeaconFunction as DeployBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon'; import { DeployBeaconProxyFunction as DeployBeaconProxyFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-beacon-proxy'; import { UpgradeBeaconFunction as UpgradeBeaconFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/upgrade-beacon'; -import { DeployAdminFunction as DeployAdminFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/deploy-proxy-admin'; import { ForceImportFunction as ForceImportFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/force-import'; import { ChangeAdminFunction as ChangeAdminFunctionOZ, TransferProxyAdminOwnershipFunction as TransferProxyAdminOwnershipFunctionOZ, - GetInstanceFunction as GetInstanceFunctionOZ, } from '@openzeppelin/hardhat-upgrades/dist/admin'; import { ValidateImplementationFunction as ValidateImplementationFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-implementation'; import { ValidateUpgradeFunction as ValidateUpgradeFunctionOZ } from '@openzeppelin/hardhat-upgrades/dist/validate-upgrade'; @@ -22,14 +20,6 @@ import { GetUpgradeApprovalProcessFunction as GetUpgradeApprovalProcessFunctionOZ, } from '@openzeppelin/hardhat-upgrades/dist/defender/get-approval-process'; -import type { ProposeUpgradeFunction as ProposeUpgradeFunctionOZ } from '../openzeppelin-hardhat-upgrades/defender-v1/propose-upgrade'; -import type { - VerifyDeployFunction as VerifyDeployFunctionOZ, - VerifyDeployWithUploadedArtifactFunction as VerifyDeployWithUploadedArtifactFunctionOZ, - GetVerifyDeployArtifactFunction as GetVerifyDeployArtifactFunctionOZ, - GetVerifyDeployBuildInfoFunction as GetVerifyDeployBuildInfoFunctionOZ, - GetBytecodeDigestFunction as GetBytecodeDigestFunctionOZ, -} from '../openzeppelin-hardhat-upgrades/defender-v1/verify-deployment'; import { UndefinedFunctionType } from '../utils'; export interface HardhatUpgradesOZ { @@ -42,12 +32,9 @@ export interface HardhatUpgradesOZ { deployBeacon: DeployBeaconFunctionOZ; deployBeaconProxy: DeployBeaconProxyFunctionOZ; upgradeBeacon: UpgradeBeaconFunctionOZ; - deployProxyAdmin: DeployAdminFunctionOZ; forceImport: ForceImportFunctionOZ; silenceWarnings: typeof silenceWarnings; admin: { - // property from zksync - getInstance: GetInstanceFunctionOZ; changeProxyAdmin: ChangeAdminFunctionOZ; transferProxyAdminOwnership: TransferProxyAdminOwnershipFunctionOZ; }; @@ -67,15 +54,6 @@ export interface HardhatUpgradesOZ { }; } -export interface DefenderV1HardhatUpgradesOZ { - proposeUpgrade: ProposeUpgradeFunctionOZ; - verifyDeployment: VerifyDeployFunctionOZ; - verifyDeploymentWithUploadedArtifact: VerifyDeployWithUploadedArtifactFunctionOZ; - getDeploymentArtifact: GetVerifyDeployArtifactFunctionOZ; - getDeploymentBuildInfo: GetVerifyDeployBuildInfoFunctionOZ; - getBytecodeDigest: GetBytecodeDigestFunctionOZ; -} - export type DefenderHardhatUpgradesOZ = { deployContract: DeployContractFunctionOZ; proposeUpgradeWithApproval: any; @@ -85,5 +63,4 @@ export type DefenderHardhatUpgradesOZ = { * @deprecated Use `getUpgradeApprovalProcess` instead. */ getDefaultApprovalProcess: GetUpgradeApprovalProcessFunctionOZ; -} & HardhatUpgradesOZ & - DefenderV1HardhatUpgradesOZ; +} & HardhatUpgradesOZ; diff --git a/packages/hardhat-zksync-upgradable/src/plugin.ts b/packages/hardhat-zksync-upgradable/src/plugin.ts index 1ab17f1b3..afc0bee64 100644 --- a/packages/hardhat-zksync-upgradable/src/plugin.ts +++ b/packages/hardhat-zksync-upgradable/src/plugin.ts @@ -17,6 +17,7 @@ export async function deployBeacon( deploymentTypeProxy?: DeploymentType; saltImpl?: string; saltProxy?: string; + initialOwner?: string; noCompile?: boolean; }, ): Promise<{ @@ -40,6 +41,7 @@ export async function deployBeacon( const beacon = await hre.upgrades.deployBeacon(factory, { deploymentType: taskArgs.deploymentTypeImpl, salt: taskArgs.saltImpl, + initialOwner: taskArgs.initialOwner, }); await beacon.waitForDeployment(); @@ -73,6 +75,8 @@ export async function deployProxy( deploymentTypeProxy?: DeploymentType; saltImpl?: string; saltProxy?: string; + initialOwner?: string; + unsafeStateVariableAssignment?: boolean; noCompile?: boolean; }, ): Promise { @@ -96,6 +100,8 @@ export async function deployProxy( deploymentTypeProxy: taskArgs.deploymentTypeProxy, saltProxy: taskArgs.saltProxy, initializer: taskArgs.initializer, + initialOwner: taskArgs.initialOwner, + unsafeAllow: taskArgs.unsafeStateVariableAssignment ? ['state-variable-assignment'] : undefined, }); await proxy.waitForDeployment(); @@ -139,6 +145,7 @@ export async function upgradeProxy( proxyAddress: string; deploymentType?: DeploymentType; salt?: string; + unsafeStateVariableAssignment?: boolean; noCompile?: boolean; }, ): Promise { @@ -154,6 +161,7 @@ export async function upgradeProxy( const proxyUpgrade = await hre.upgrades.upgradeProxy(wallet, taskArgs.proxyAddress, contractV2, { deploymentType: taskArgs.deploymentType, salt: taskArgs.salt, + unsafeAllow: taskArgs.unsafeStateVariableAssignment ? ['state-variable-assignment'] : undefined, }); await proxyUpgrade.waitForDeployment(); diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts index ea13c5282..60ca4f663 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon-proxy.ts @@ -11,13 +11,10 @@ import * as zk from 'zksync-ethers'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import chalk from 'chalk'; -import assert from 'assert'; -import path from 'path'; import { ContractAddressOrInstance, getContractAddress, getInitializerData } from '../utils/utils-general'; import { DeployBeaconProxyOptions } from '../utils/options'; -import { BEACON_PROXY_JSON } from '../constants'; import { Manifest } from '../core/manifest'; -import { getUpgradableContracts } from '../utils'; +import { getBeaconProxyFactory } from '../utils/factories'; import { deploy, DeployTransaction } from './deploy'; export type DeployBeaconProxyFactory = ( @@ -123,18 +120,7 @@ async function deployBeaconProxy( } } - const beaconProxyPath = (await hre.artifacts.getArtifactPaths()).find((artifactPath) => - artifactPath.includes(path.sep + getUpgradableContracts().BeaconProxy + path.sep + BEACON_PROXY_JSON), - ); - assert(beaconProxyPath, 'Beacon proxy artifact not found'); - const beaconProxyContract = await import(beaconProxyPath); - - const beaconProxyFactory = new zk.ContractFactory( - beaconProxyContract.abi, - beaconProxyContract.bytecode, - wallet, - opts.deploymentType, - ); + const beaconProxyFactory = await getBeaconProxyFactory(hre, wallet, opts.deploymentType); const proxyDeployment: Required = { kind: opts.kind!, diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts index efa49f61b..6ec18692b 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-beacon.ts @@ -6,13 +6,10 @@ import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import * as zk from 'zksync-ethers'; import chalk from 'chalk'; -import assert from 'assert'; -import path from 'path'; -import { UPGRADABLE_BEACON_JSON } from '../constants'; import { extractFactoryDeps, getArtifactFromBytecode } from '../utils/utils-general'; import { ZkSyncUpgradablePluginError } from '../errors'; import { DeployBeaconOptions } from '../utils/options'; -import { getUpgradableContracts } from '../utils'; +import { getUpgradeableBeaconFactory } from '../utils/factories'; import { deployBeaconImpl } from './deploy-impl'; import { deploy, DeployTransaction } from './deploy'; @@ -92,18 +89,13 @@ async function deployProxyBeacon( console.info(chalk.green('Beacon impl deployed at', impl)); } - const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), - ); - assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); - const upgradeableBeaconContract = await import(upgradableBeaconPath); + const upgradeableBeaconFactory = await getUpgradeableBeaconFactory(hre, wallet); - const upgradeableBeaconFactory = new zk.ContractFactory( - upgradeableBeaconContract.abi, - upgradeableBeaconContract.bytecode, - wallet, + const beaconDeployment: Required = await deploy( + upgradeableBeaconFactory, + impl, + opts.initialOwner ?? wallet.address, ); - const beaconDeployment: Required = await deploy(upgradeableBeaconFactory, impl); if (!quiet) { console.info(chalk.green('Beacon deployed at: ', beaconDeployment.address)); } diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts index dabaabba5..2bca4d648 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-impl.ts @@ -13,7 +13,6 @@ import { TransactionResponse } from 'zksync-ethers/src/types'; import { DeployProxyOptions, UpgradeOptions, withDefaults } from '../utils/options'; import { validateBeaconImpl, validateProxyImpl } from '../validations/validate-impl'; import { readValidations } from '../validations/validations'; - import { fetchOrDeployGetDeployment } from '../core/impl-store'; import { FORMAT_TYPE_MINIMAL, IMPL_CONTRACT_NOT_DEPLOYED_ERROR } from '../constants'; import { ZkSyncUpgradablePluginError } from '../errors'; diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts deleted file mode 100644 index 2f19cb887..000000000 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy-admin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { HardhatRuntimeEnvironment } from 'hardhat/types'; -import * as zk from 'zksync-ethers'; -import path from 'path'; -import assert from 'assert'; -import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; -import { DeploymentType } from 'zksync-ethers/build/types'; -import { DeployProxyAdminOptions } from '../utils/options'; -import { PROXY_ADMIN_JSON } from '../constants'; -import { fetchOrDeployAdmin } from '../core/impl-store'; -import { getUpgradableContracts } from '../utils'; -import { deploy } from './deploy'; - -export type DeployAdminFunction = (wallet?: zk.Wallet, opts?: DeployProxyAdminOptions) => Promise; - -export function makeDeployProxyAdmin(hre: HardhatRuntimeEnvironment): any { - return async function deployProxyAdmin(wallet: zk.Wallet, opts: DeployProxyAdminOptions = {}) { - const adminFactory = await getAdminFactory(hre, wallet, opts.deploymentType); - return await fetchOrDeployAdmin( - wallet.provider, - () => - deploy(adminFactory, { - customData: { - salt: opts.salt, - paymasterParams: opts.paymasterParams, - ...opts.otherCustomData, - }, - }), - opts, - ); - }; -} - -export async function getAdminArtifact(hre: HardhatRuntimeEnvironment): Promise { - const proxyAdminPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ProxyAdmin + path.sep + PROXY_ADMIN_JSON), - ); - assert(proxyAdminPath, 'Proxy admin artifact not found'); - return await import(proxyAdminPath); -} - -export async function getAdminFactory( - hre: HardhatRuntimeEnvironment, - wallet: zk.Wallet, - deploymentType?: DeploymentType, -): Promise> { - const proxyAdminContract = await getAdminArtifact(hre); - return new zk.ContractFactory( - proxyAdminContract.abi, - proxyAdminContract.bytecode, - wallet, - deploymentType, - ); -} diff --git a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts index 3c1959029..5a46a7654 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-deployment/deploy-proxy.ts @@ -1,18 +1,19 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types'; import * as zk from 'zksync-ethers'; import chalk from 'chalk'; -import path from 'path'; import { BeaconProxyUnsupportedError } from '@openzeppelin/upgrades-core'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; -import assert from 'assert'; import { extractFactoryDeps, getArtifactFromBytecode, getInitializerData } from '../utils/utils-general'; -import { ERC1967_PROXY_JSON, TUP_JSON } from '../constants'; import { Manifest, ProxyDeployment } from '../core/manifest'; import { ZkSyncUpgradablePluginError } from '../errors'; import { DeployProxyOptions } from '../utils/options'; -import { getUpgradableContracts } from '../utils'; +import { + getProxyFactory, + getTransparentUpgradeableProxyArtifact, + getTransparentUpgradeableProxyFactory, +} from '../utils/factories'; import { deployProxyImpl } from './deploy-impl'; import { DeployTransaction, deploy } from './deploy'; @@ -132,14 +133,6 @@ async function deployProxy( const data = getInitializerData(factory.interface, args, opts.initializer); - const customDataProxy = { - customData: { - salt: opts.saltProxy, - paymasterParams: opts.paymasterProxyParams, - ...opts.otherCustomData, - }, - }; - if (kind === 'uups') { if (await manifest.getAdmin()) { if (!quiet) { @@ -159,18 +152,17 @@ async function deployProxy( } case 'uups': { - const ERC1967ProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ERC1967Proxy + path.sep + ERC1967_PROXY_JSON), - ); - assert(ERC1967ProxyPath, 'ERC1967Proxy artifact not found'); - const proxyContract = await import(ERC1967ProxyPath); - const proxyFactory = new zk.ContractFactory( - proxyContract.abi, - proxyContract.bytecode, - wallet, - opts.deploymentTypeProxy, - ); - proxyDeployment = { kind, ...(await deploy(proxyFactory, impl, data, customDataProxy)) }; + const proxyFactory = await getProxyFactory(hre, wallet, opts.deploymentTypeProxy); + + const customDataProxyUups = { + customData: { + salt: opts.saltProxy, + paymasterParams: opts.paymasterProxyParams, + ...opts.otherCustomData, + }, + }; + + proxyDeployment = { kind, ...(await deploy(proxyFactory, impl, data, customDataProxyUups)) }; if (!quiet) { console.info(chalk.green(`UUPS proxy was deployed to ${proxyDeployment.address}`)); @@ -179,27 +171,21 @@ async function deployProxy( } case 'transparent': { - const adminAddress = await hre.upgrades.deployProxyAdmin(wallet, { - paymasterParams: opts.paymasterProxyParams, - }); + const TUPFactory = await getTransparentUpgradeableProxyFactory(hre, wallet, opts.deploymentTypeProxy); + const TUPArtifact = await getTransparentUpgradeableProxyArtifact(hre); - if (!quiet) { - console.info(chalk.green(`Admin was deployed to ${adminAddress}`)); - } + const initialOwner = opts.initialOwner ?? wallet.address; + + const customDataProxyTup = { + customData: { + salt: opts.saltProxy, + factoryDeps: await extractFactoryDeps(hre, TUPArtifact), + paymasterParams: opts.paymasterProxyParams, + ...opts.otherCustomData, + }, + }; - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + TUP_JSON), - ); - assert(TUPPath, 'TUP artifact not found'); - const TUPContract = await import(TUPPath); - - const TUPFactory = new zk.ContractFactory( - TUPContract.abi, - TUPContract.bytecode, - wallet, - opts.deploymentTypeProxy, - ); - proxyDeployment = { kind, ...(await deploy(TUPFactory, impl, adminAddress, data, customDataProxy)) }; + proxyDeployment = { kind, ...(await deploy(TUPFactory, impl, initialOwner, data, customDataProxyTup)) }; if (!quiet) { console.info(chalk.green(`Transparent proxy was deployed to ${proxyDeployment.address}`)); diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts index 86f3cb6ce..1ffb5c2a7 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-beacon.ts @@ -1,10 +1,8 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import * as zk from 'zksync-ethers'; -import path from 'path'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import chalk from 'chalk'; -import assert from 'assert'; import { ContractAddressOrInstance, extractFactoryDeps, @@ -13,9 +11,8 @@ import { } from '../utils/utils-general'; import { UpgradeBeaconOptions } from '../utils/options'; import { deployBeaconImpl } from '../proxy-deployment/deploy-impl'; -import { UPGRADABLE_BEACON_JSON } from '../constants'; import { ZkSyncUpgradablePluginError } from '../errors'; -import { getUpgradableContracts } from '../utils'; +import { getUpgradeableBeaconFactory } from '../utils/factories'; export type UpgradeBeaconFactory = ( beacon: ContractAddressOrInstance, @@ -81,17 +78,7 @@ async function upgradeBeacon( console.info(chalk.green('New beacon impl deployed at', nextImpl)); } - const upgradableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), - ); - assert(upgradableBeaconPath, 'Upgradable beacon artifact not found'); - const upgradeableBeaconContract = await import(upgradableBeaconPath); - - const upgradeableBeaconFactory = new zk.ContractFactory( - upgradeableBeaconContract.abi, - upgradeableBeaconContract.bytecode, - wallet, - ); + const upgradeableBeaconFactory = await getUpgradeableBeaconFactory(hre, wallet); const beaconContract = upgradeableBeaconFactory.attach(beaconImplementationAddress); const upgradeTx = await beaconContract.upgradeTo(nextImpl); diff --git a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts index 530435641..e4c087d94 100644 --- a/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts +++ b/packages/hardhat-zksync-upgradable/src/proxy-upgrade/upgrade-proxy.ts @@ -1,21 +1,22 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import * as zk from 'zksync-ethers'; import { TransactionResponse } from 'zksync-ethers/src/types'; -import path from 'path'; -import { getAdminAddress, getCode, isEmptySlot } from '@openzeppelin/upgrades-core'; +import { getAdminAddress, getCode, getUpgradeInterfaceVersion, isEmptySlot } from '@openzeppelin/upgrades-core'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; import chalk from 'chalk'; -import assert from 'assert'; import { ContractAddressOrInstance } from '../interfaces'; import { UpgradeProxyOptions } from '../utils/options'; import { extractFactoryDeps, getArtifactFromBytecode, getContractAddress } from '../utils/utils-general'; import { deployProxyImpl } from '../proxy-deployment/deploy-impl'; -import { Manifest } from '../core/manifest'; -import { ITUP_JSON, PROXY_ADMIN_JSON } from '../constants'; import { ZkSyncUpgradablePluginError } from '../errors'; -import { getUpgradableContracts } from '../utils'; +import { + attachITransparentUpgradeableProxyV4, + attachITransparentUpgradeableProxyV5, + attachProxyAdminV4, + attachProxyAdminV5, +} from '../utils/attach-abi'; export type UpgradeProxyFactory = ( proxy: ContractAddressOrInstance, @@ -111,44 +112,37 @@ async function getUpgrader(hre: HardhatRuntimeEnvironment, proxyAddress: string, const adminBytecode = await getCode(provider, adminAddress); if (isEmptySlot(adminAddress) || adminBytecode === '0x') { - const TUPPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + ITUP_JSON), - ); - assert(TUPPath, 'Transparent upgradeable proxy artifact not found'); - const transparentUpgradeableProxyContract = await import(TUPPath); - - const transparentUpgradeableProxyFactory = new zk.ContractFactory( - transparentUpgradeableProxyContract.abi, - transparentUpgradeableProxyContract.bytecode, - wallet, - ); - const proxy = transparentUpgradeableProxyFactory.attach(proxyAddress); - - return (nextImpl, call) => (call ? proxy.upgradeToAndCall(nextImpl, call) : proxy.upgradeTo(nextImpl)); + const upgradeInterfaceVersion = await getUpgradeInterfaceVersion(provider, proxyAddress); + if (upgradeInterfaceVersion === '5.0.0') { + const proxyV5 = await attachITransparentUpgradeableProxyV5(proxyAddress, wallet); + return (nextImpl, call) => proxyV5.upgradeToAndCall(nextImpl, call ?? '0x'); + } + if (upgradeInterfaceVersion !== undefined) { + // Log as debug if the interface version is an unknown string. + // Do not throw an error because this could be caused by a fallback function. + console.debug( + `Unknown UPGRADE_INTERFACE_VERSION ${upgradeInterfaceVersion} for proxy at ${proxyAddress}. Expected 5.0.0`, + ); + } + const proxyV4 = await attachITransparentUpgradeableProxyV4(proxyAddress, wallet); + return (nextImpl, call) => (call ? proxyV4.upgradeToAndCall(nextImpl, call) : proxyV4.upgradeTo(nextImpl)); } else { - const manifest = await Manifest.forNetwork(provider); - - const proxyAdminPath = (await hre.artifacts.getArtifactPaths()).find((x) => - x.includes(path.sep + getUpgradableContracts().ProxyAdmin + path.sep + PROXY_ADMIN_JSON), - ); - assert(proxyAdminPath, 'Proxy admin artifact not found'); - const proxyAdminContract = await import(proxyAdminPath); - - const proxyAdminFactory = new zk.ContractFactory( - proxyAdminContract.abi, - proxyAdminContract.bytecode, - wallet, - ); + const upgradeInterfaceVersion = await getUpgradeInterfaceVersion(provider, adminAddress); - const admin = proxyAdminFactory.attach(adminAddress); - const manifestAdmin = await manifest.getAdmin(); - - if ((await admin.getAddress()) !== manifestAdmin?.address) { - throw new Error('Proxy admin is not the one registered in the network manifest'); + if (upgradeInterfaceVersion === '5.0.0') { + const adminV5 = await attachProxyAdminV5(adminAddress, wallet); + return (nextImpl, call) => adminV5.upgradeAndCall(proxyAddress, nextImpl, call ?? '0x'); } - + if (upgradeInterfaceVersion !== undefined) { + // Log as debug if the interface version is an unknown string. + // Do not throw an error because this could be caused by a fallback function. + console.debug( + `Unknown UPGRADE_INTERFACE_VERSION ${upgradeInterfaceVersion} for proxy at ${proxyAddress}. Expected 5.0.0`, + ); + } + const adminV4 = await attachProxyAdminV4(adminAddress, wallet); return (nextImpl, call) => - call ? admin.upgradeAndCall(proxyAddress, nextImpl, call) : admin.upgrade(proxyAddress, nextImpl); + call ? adminV4.upgradeAndCall(proxyAddress, nextImpl, call) : adminV4.upgrade(proxyAddress, nextImpl); } } diff --git a/packages/hardhat-zksync-upgradable/src/utils.ts b/packages/hardhat-zksync-upgradable/src/utils.ts index a5d76272b..34553b8c3 100644 --- a/packages/hardhat-zksync-upgradable/src/utils.ts +++ b/packages/hardhat-zksync-upgradable/src/utils.ts @@ -63,7 +63,7 @@ export function isOpenzeppelinContractsVersionValid(): boolean { try { // eslint-disable-next-line import/no-extraneous-dependencies const versionContracts = require('@openzeppelin/contracts/package.json').version; - if (!versionContracts || semver.lt(versionContracts, '4.6.0') || semver.gt(versionContracts, '5.0.0')) { + if (!versionContracts || semver.lt(versionContracts, '5.0.0')) { return false; } return true; diff --git a/packages/hardhat-zksync-upgradable/src/utils/attach-abi.ts b/packages/hardhat-zksync-upgradable/src/utils/attach-abi.ts new file mode 100644 index 000000000..eebcbaaca --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/utils/attach-abi.ts @@ -0,0 +1,35 @@ +import ITransparentUpgradeableProxyV5 from '@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json'; +import ITransparentUpgradeableProxyV4 from '@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json'; + +import ProxyAdminV5 from '@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json'; +import ProxyAdminV4 from '@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json'; + +import { Contract, ContractFactory, Wallet } from 'zksync-ethers'; + +export async function attachITransparentUpgradeableProxyV5(address: string, wallet?: Wallet): Promise { + const contractFactory = new ContractFactory( + ITransparentUpgradeableProxyV5.abi, + ITransparentUpgradeableProxyV5.bytecode, + wallet, + ); + return contractFactory.attach(address); +} + +export async function attachITransparentUpgradeableProxyV4(address: string, wallet?: Wallet): Promise { + const contractFactory = new ContractFactory( + ITransparentUpgradeableProxyV4.abi, + ITransparentUpgradeableProxyV4.bytecode, + wallet, + ); + return contractFactory.attach(address); +} + +export async function attachProxyAdminV5(address: string, wallet?: Wallet): Promise { + const contractFactory = new ContractFactory(ProxyAdminV5.abi, ProxyAdminV5.bytecode, wallet); + return contractFactory.attach(address); +} + +export async function attachProxyAdminV4(address: string, wallet?: Wallet): Promise { + const contractFactory = new ContractFactory(ProxyAdminV4.abi, ProxyAdminV4.bytecode, wallet); + return contractFactory.attach(address); +} diff --git a/packages/hardhat-zksync-upgradable/src/utils/factories.ts b/packages/hardhat-zksync-upgradable/src/utils/factories.ts new file mode 100644 index 000000000..1856f22aa --- /dev/null +++ b/packages/hardhat-zksync-upgradable/src/utils/factories.ts @@ -0,0 +1,120 @@ +import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-deploy/src/types'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import path from 'path'; + +import { Contract, ContractFactory, Wallet } from 'zksync-ethers'; +import assert from 'assert'; +import { DeploymentType } from 'zksync-ethers/src/types'; +import { + BEACON_PROXY_JSON, + ERC1967_PROXY_JSON, + PROXY_ADMIN_JSON, + TUP_JSON, + UPGRADABLE_BEACON_JSON, +} from '../constants'; +import { getUpgradableContracts } from '../utils'; + +export async function getProxyArtifact(hre: HardhatRuntimeEnvironment): Promise { + const proxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().ERC1967Proxy + path.sep + ERC1967_PROXY_JSON), + ); + assert(proxyPath, 'Proxy artifact not found'); + return await import(proxyPath); +} + +export async function getProxyFactory( + hre: HardhatRuntimeEnvironment, + wallet: Wallet, + deploymentType?: DeploymentType, +): Promise> { + const proxyContract = await getProxyArtifact(hre); + return new ContractFactory(proxyContract.abi, proxyContract.bytecode, wallet, deploymentType); +} + +export async function getTransparentUpgradeableProxyArtifact(hre: HardhatRuntimeEnvironment): Promise { + const transparentUpgradeableProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().TransparentUpgradeableProxy + path.sep + TUP_JSON), + ); + assert(transparentUpgradeableProxyPath, 'Transparent upgradeable proxy artifact not found'); + return await import(transparentUpgradeableProxyPath); +} + +export async function getTransparentUpgradeableProxyFactory( + hre: HardhatRuntimeEnvironment, + wallet: Wallet, + deploymentType?: DeploymentType, +): Promise> { + const transparentUpgradeableProxy = await getTransparentUpgradeableProxyArtifact(hre); + return new ContractFactory( + transparentUpgradeableProxy.abi, + transparentUpgradeableProxy.bytecode, + wallet, + deploymentType, + ); +} + +export async function getBeaconProxyArtifact(hre: HardhatRuntimeEnvironment): Promise { + const beaconProxyPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().BeaconProxy + path.sep + BEACON_PROXY_JSON), + ); + assert(beaconProxyPath, 'Beacon proxy artifact not found'); + return await import(beaconProxyPath); +} + +export async function getBeaconProxyFactory( + hre: HardhatRuntimeEnvironment, + wallet: Wallet, + deploymentType?: DeploymentType, +): Promise> { + const beaconProxyArtifact = await getBeaconProxyArtifact(hre); + return new ContractFactory( + beaconProxyArtifact.abi, + beaconProxyArtifact.bytecode, + wallet, + deploymentType, + ); +} + +export async function getUpgradableBeaconArtifact(hre: HardhatRuntimeEnvironment): Promise { + const upgradeableBeaconPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().UpgradeableBeacon + path.sep + UPGRADABLE_BEACON_JSON), + ); + assert(upgradeableBeaconPath, 'Upgradeable beacon artifact not found'); + return await import(upgradeableBeaconPath); +} + +export async function getUpgradeableBeaconFactory( + hre: HardhatRuntimeEnvironment, + wallet: Wallet, + deploymentType?: DeploymentType, +): Promise> { + const upgradeableBeaconContract = await getUpgradableBeaconArtifact(hre); + return new ContractFactory( + upgradeableBeaconContract.abi, + upgradeableBeaconContract.bytecode, + wallet, + deploymentType, + ); +} + +export async function getProxyAdminArtifact(hre: HardhatRuntimeEnvironment): Promise { + const proxyAdminPath = (await hre.artifacts.getArtifactPaths()).find((x) => + x.includes(path.sep + getUpgradableContracts().ProxyAdmin + path.sep + PROXY_ADMIN_JSON), + ); + assert(proxyAdminPath, 'Proxy admin artifact not found'); + return await import(proxyAdminPath); +} + +export async function getProxyAdminFactory( + hre: HardhatRuntimeEnvironment, + wallet: Wallet, + deploymentType?: DeploymentType, +): Promise> { + const proxyAdminContract = await getProxyAdminArtifact(hre); + return new ContractFactory( + proxyAdminContract.abi, + proxyAdminContract.bytecode, + wallet, + deploymentType, + ); +} diff --git a/packages/hardhat-zksync-upgradable/src/utils/options.ts b/packages/hardhat-zksync-upgradable/src/utils/options.ts index aa43a8e07..2cfe87ace 100644 --- a/packages/hardhat-zksync-upgradable/src/utils/options.ts +++ b/packages/hardhat-zksync-upgradable/src/utils/options.ts @@ -17,7 +17,12 @@ export type StandaloneOptions; + } & CustomDataOptions & + InitialOwnerType; + +export interface InitialOwnerType { + initialOwner?: string; +} export type CustomDataOptions = TRequiredSeperateForProxy extends true | undefined @@ -61,7 +66,6 @@ interface Initializer { export type DeployBeaconProxyOptions = ProxyKindOption & Initializer & CustomDataOptions; export type DeployBeaconOptions = StandaloneOptions; export type DeployImplementationOptions = StandaloneOptions; -export type DeployProxyAdminOptions = DeployOpts & CustomDataOptions; export type DeployProxyOptions = StandaloneOptions & Initializer; export type UpgradeBeaconOptions = UpgradeOptions; export type UpgradeProxyOptions = UpgradeOptions & { diff --git a/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts b/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts index 20502c24d..dec3dac25 100644 --- a/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts +++ b/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts @@ -1,27 +1,35 @@ import { assertNotProxy, + assertStorageUpgradeSafe, assertUpgradeSafe, getImplementationAddress, getImplementationAddressFromBeacon, + getStorageLayoutForAddress, + Manifest, + processProxyKind, ValidationOptions, - assertStorageUpgradeSafe, } from '@openzeppelin/upgrades-core'; -import { getStorageLayoutForAddress } from '../core/manifest-storage-layout'; -import { Manifest } from '../core/manifest'; import { DeployData } from '../proxy-deployment/deploy-impl'; -import { processProxyKind } from '../core/proxy-kind'; +/** + * Processes the proxy kind and returns the implementation address if proxyAddress is provided. + */ async function processProxyImpl(deployData: DeployData, proxyAddress: string | undefined, opts: ValidationOptions) { await processProxyKind(deployData.provider, proxyAddress, opts, deployData.validations, deployData.version); let currentImplAddress: string | undefined; if (proxyAddress !== undefined) { + // upgrade scenario currentImplAddress = await getImplementationAddress(deployData.provider, proxyAddress); } return currentImplAddress; } +/** + * Asserts that the address is not a proxy and returns the beacon's implementation address. + */ async function processBeaconImpl(deployData: DeployData, beaconAddress: string) { + // upgrade scenario await assertNotProxy(deployData.provider, beaconAddress); return await getImplementationAddressFromBeacon(deployData.provider, beaconAddress); } @@ -42,6 +50,10 @@ export async function validateImpl( } } +/** + * Processes the proxy kind and validates that the implementation in deployData is upgrade safe + * (compared to the proxy's current implementation if proxyAddress is specified). + */ export async function validateProxyImpl( deployData: DeployData, opts: ValidationOptions, @@ -51,6 +63,10 @@ export async function validateProxyImpl( return validateImpl(deployData, opts, currentImplAddress); } +/** + * Asserts that the address is not a proxy and validates that the implementation in deployData is upgrade safe + * compared to the beacon's current implementation. + */ export async function validateBeaconImpl( deployData: DeployData, opts: ValidationOptions, diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/deployment-gas-estimation/contracts/BoxUups.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/deployment-gas-estimation/contracts/BoxUups.sol index 0b3345dd7..0bd67e5bb 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/deployment-gas-estimation/contracts/BoxUups.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/deployment-gas-estimation/contracts/BoxUups.sol @@ -11,7 +11,7 @@ contract BoxUups is Initializable, UUPSUpgradeable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUups.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUups.sol index 0b3345dd7..0bd67e5bb 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUups.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUups.sol @@ -11,7 +11,7 @@ contract BoxUups is Initializable, UUPSUpgradeable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsMissingUpgradeTo.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsMissingUpgradeTo.sol index bbd42edf5..0515d10fe 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsMissingUpgradeTo.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsMissingUpgradeTo.sol @@ -11,7 +11,7 @@ contract BoxUupsMissingUpgradeTo is Initializable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); } // Reads the last stored value diff --git a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsPublic.sol b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsPublic.sol index 2acadd47f..a2a716085 100644 --- a/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsPublic.sol +++ b/packages/hardhat-zksync-upgradable/test/fixture-projects/uups-e2e/contracts/BoxUupsPublic.sol @@ -11,7 +11,7 @@ contract BoxUupsPublic is Initializable, UUPSUpgradeable, OwnableUpgradeable { function initialize(uint256 initValue) public initializer { value = initValue; - __Ownable_init(); + __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } diff --git a/packages/hardhat-zksync-upgradable/test/tests.ts b/packages/hardhat-zksync-upgradable/test/tests.ts index 99772df49..0100f0d2b 100644 --- a/packages/hardhat-zksync-upgradable/test/tests.ts +++ b/packages/hardhat-zksync-upgradable/test/tests.ts @@ -1,16 +1,13 @@ import assert from 'assert'; import { ContractFactory, Provider, Contract } from 'zksync-ethers'; import chalk from 'chalk'; -import fsExtra from 'fs-extra'; -import path from 'path'; import { getAdminAddress } from '@openzeppelin/upgrades-core'; -import { LOCAL_SETUP_ZKSYNC_NETWORK, MANIFEST_DEFAULT_DIR } from '../src/constants'; -import { getAdminFactory } from '../src/proxy-deployment/deploy-proxy-admin'; +import { LOCAL_SETUP_ZKSYNC_NETWORK } from '../src/constants'; import { deploy } from '../src/proxy-deployment/deploy'; -import { getManifestAdmin } from '../src/admin'; import { deployBeacon, deployProxy, upgradeBeacon } from '../src/plugin'; -import { TEST_ADDRESS, authorizationErrors, standaloneValidationErrors, storageLayoutErrors } from './constants'; +import { getProxyAdminFactory } from '../src/utils/factories'; +import { TEST_ADDRESS, standaloneValidationErrors, storageLayoutErrors } from './constants'; import richWallets from './rich-wallets.json'; import { useEnvironment } from './helpers'; @@ -93,6 +90,7 @@ describe('Upgradable plugin tests', function () { const boxArtifact = await this.deployer.loadArtifact(contractName1); boxUupsProxy = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, boxArtifact, [42], { initializer: 'initialize', + unsafeAllow: ['state-variable-assignment'], }); await boxUupsProxy.waitForDeployment(); @@ -105,6 +103,7 @@ describe('Upgradable plugin tests', function () { [42], { initializer: 'initialize', + unsafeAllow: ['state-variable-assignment'], }, ); await boxUupsPublicProxy.waitForDeployment(); @@ -129,6 +128,9 @@ describe('Upgradable plugin tests', function () { this.deployer.zkWallet, await boxUupsProxy.getAddress(), BoxV2, + { + unsafeAllow: ['state-variable-assignment'], + }, ); await new Promise((resolve) => setTimeout(resolve, 1500)); box2.connect(this.deployer.zkWallet); @@ -142,8 +144,9 @@ describe('Upgradable plugin tests', function () { const BoxV2 = await this.deployer.loadArtifact(contractName); await assert.rejects( - this.env.zkUpgrades.upgradeProxy(this.zkWallet2, await boxUupsProxy.getAddress(), BoxV2), - (error: any) => error.message.includes(authorizationErrors.CALLER_NOT_OWNER), + this.env.zkUpgrades.upgradeProxy(this.zkWallet2, await boxUupsProxy.getAddress(), BoxV2, { + unsafeAllow: ['state-variable-assignment'], + }), ); }); @@ -157,6 +160,9 @@ describe('Upgradable plugin tests', function () { this.zkWallet2, await boxUupsPublicProxy.getAddress(), BoxV2, + { + unsafeAllow: ['state-variable-assignment'], + }, ); await box2.waitForDeployment(); console.info(chalk.green('Successfully upgraded BoxUupsPublic to BoxUupsV2')); @@ -177,6 +183,7 @@ describe('Upgradable plugin tests', function () { this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', kind: 'uups', + unsafeAllow: ['state-variable-assignment'], }), (error: any) => error.message.includes(standaloneValidationErrors.MISSING_PUBLIC_UPGRADE_TO), ); @@ -191,6 +198,7 @@ describe('Upgradable plugin tests', function () { await assert.rejects( this.env.zkUpgrades.upgradeProxy(this.deployer.zkWallet, await boxUupsProxy.getAddress(), boxV2, { kind: 'uups', + unsafeAllow: ['state-variable-assignment'], }), (error: any) => error.message.includes(standaloneValidationErrors.MISSING_PUBLIC_UPGRADE_TO) && @@ -259,31 +267,6 @@ describe('Upgradable plugin tests', function () { const provider = new Provider(LOCAL_SETUP_ZKSYNC_NETWORK); - it('Should return the smart contract admin instance', async function () { - const contractName = 'Box'; - console.info(chalk.yellow(`Deploying ${contractName}...`)); - - const contract = await this.deployer.loadArtifact(contractName); - const deployedContract = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { - initializer: 'store', - }); - await deployedContract.waitForDeployment(); - - const adminInstance = await this.env.zkUpgrades.admin.getInstance(this.deployer.zkWallet); - const adminAddress = await adminInstance.getProxyAdmin(await deployedContract.getAddress()); - - assert(await adminInstance.getAddress(), adminAddress); - }); - - it('Should fail to return the smart contract admin instance', async function () { - // remove the manifest file to separate this test's manifest file from others - await fsExtra.remove(path.join(this.env.config.paths.root, MANIFEST_DEFAULT_DIR)); - - await assert.rejects(this.env.zkUpgrades.admin.getInstance(this.deployer.zkWallet), (error: any) => - error.message.includes(authorizationErrors.NO_PROXY_ADMIN_FOUND), - ); - }); - it('Should change the admin of an upgradable smart contract', async function () { const contractName = 'Box'; console.info(chalk.yellow(`Deploying ${contractName}...`)); @@ -293,8 +276,7 @@ describe('Upgradable plugin tests', function () { initializer: 'initialize', }); - const adminInstance = await this.env.zkUpgrades.admin.getInstance(this.deployer.zkWallet); - await this.env.zkUpgrades.admin.changeProxyAdmin( + await this.env.zkUpgrades.admin.transferProxyAdminOwnership( await deployedContract.getAddress(), richWallets[1].address, this.deployer.zkWallet, @@ -304,7 +286,6 @@ describe('Upgradable plugin tests', function () { await new Promise((resolve) => setTimeout(resolve, 2000)); const updatedAdminInstance = await getAdminAddress(provider, await deployedContract.getAddress()); - assert(updatedAdminInstance !== (await adminInstance.getAddress())); assert(updatedAdminInstance, richWallets[1].address); }); @@ -319,10 +300,10 @@ describe('Upgradable plugin tests', function () { initializer: 'initialize', }); - const adminFactory = await getAdminFactory(this.env, this.zkWallet2); - const newAdminContract = await deploy(adminFactory); + const adminFactory = await getProxyAdminFactory(this.env, this.zkWallet2); + const newAdminContract = await deploy(adminFactory, this.deployer.zkWallet.address); - await this.env.zkUpgrades.admin.changeProxyAdmin( + await this.env.zkUpgrades.admin.transferProxyAdminOwnership( await deployedContract.getAddress(), newAdminContract.address, this.deployer.zkWallet, @@ -337,11 +318,10 @@ describe('Upgradable plugin tests', function () { await deployedContract.getAddress(), contractV2, ), - (error: any) => error.message.includes(authorizationErrors.WRONG_PROXY_ADMIN), ); }); - it('Should fail to change the admin - wrong signer', async function () { + it.only('Should fail to change the admin - wrong signer', async function () { const contractName = 'Box'; console.info(chalk.yellow(`Deploying ${contractName}...`)); @@ -351,12 +331,11 @@ describe('Upgradable plugin tests', function () { }); await assert.rejects( - this.env.zkUpgrades.admin.changeProxyAdmin( + this.env.zkUpgrades.admin.transferProxyAdminOwnership( await deployedContract.getAddress(), richWallets[1].address, this.zkWallet2, ), - (error: any) => error.message.includes(authorizationErrors.CALLER_NOT_OWNER), ); }); @@ -365,16 +344,17 @@ describe('Upgradable plugin tests', function () { console.info(chalk.yellow(`Deploying ${contractName}...`)); const contract = await this.deployer.loadArtifact(contractName); - await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { + const proxy = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', }); - const admin = await getManifestAdmin(this.env, this.deployer.zkWallet); - - await this.env.zkUpgrades.admin.transferProxyAdminOwnership(TEST_ADDRESS, this.deployer.zkWallet); - const newOwner = await admin.owner(); - - assert(newOwner, TEST_ADDRESS); + await this.env.zkUpgrades.admin.transferProxyAdminOwnership( + await proxy.getAddress(), + TEST_ADDRESS, + this.deployer.zkWallet, + ); + const savedAdmin = await getAdminAddress(provider, await proxy.getAddress()); + assert(savedAdmin, TEST_ADDRESS); }); it('Should fail to change the owner - wrong signer', async function () { @@ -382,23 +362,16 @@ describe('Upgradable plugin tests', function () { console.info(chalk.yellow(`Deploying ${contractName}...`)); const contract = await this.deployer.loadArtifact(contractName); - await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { + const proxy = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', }); await assert.rejects( - this.env.zkUpgrades.admin.transferProxyAdminOwnership(TEST_ADDRESS, this.zkWallet2), - (error: any) => error.message.includes(authorizationErrors.CALLER_NOT_OWNER), - ); - }); - - it('Should fail to change the owner - no admin', async function () { - // remove the manifest file to separate this test's manifest file from others - await fsExtra.remove(path.join(this.env.config.paths.root, MANIFEST_DEFAULT_DIR)); - - await assert.rejects( - this.env.zkUpgrades.admin.transferProxyAdminOwnership(TEST_ADDRESS, this.zkWallet2), - (error: any) => error.message.includes(authorizationErrors.NO_PROXY_ADMIN_FOUND), + this.env.zkUpgrades.admin.transferProxyAdminOwnership( + await proxy.getAddress(), + TEST_ADDRESS, + this.zkWallet2, + ), ); }); }); @@ -547,6 +520,7 @@ describe('Upgradable plugin tests', function () { const box = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', kind: 'uups', + unsafeAllow: ['state-variable-assignment'], }); await box.waitForDeployment(); @@ -632,6 +606,7 @@ describe('Test for upgrades for shortcuts commands', function () { const box = await deployProxy(this.env, { contractName: 'BoxUups', constructorArgsParams: [42], + unsafeStateVariableAssignment: true, }); const value = await box.retrieve(); diff --git a/packages/hardhat-zksync/package.json b/packages/hardhat-zksync/package.json index a7f6832fe..14a3243be 100644 --- a/packages/hardhat-zksync/package.json +++ b/packages/hardhat-zksync/package.json @@ -43,9 +43,9 @@ "@matterlabs/zksync-contracts": "^0.6.1", "@nomicfoundation/hardhat-ethers": "^3.0.4", "@nomicfoundation/hardhat-verify": "^2.0.0", - "@openzeppelin/upgrades-core": "^1.31.3", - "@openzeppelin/contracts-upgradeable": "^4.9.2", - "@openzeppelin/contracts": "^4.9.2", + "@openzeppelin/upgrades-core": "^1.37.0", + "@openzeppelin/contracts-upgradeable": "^5.0.2", + "@openzeppelin/contracts": "^5.0.2", "ethers": "^6.12.2", "zksync-ethers": "^6.8.0", "chai": "^4.3.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da759af2b..95ad7521c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,13 +43,13 @@ importers: version: link:../../packages/hardhat-zksync-solc '@matterlabs/zksync-contracts': specifier: ^0.6.1 - version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) + version: 0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2) '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) chalk: specifier: ^4.1.2 version: 4.1.2 @@ -287,16 +287,16 @@ importers: version: link:../../packages/hardhat-zksync-solc '@matterlabs/zksync-contracts': specifier: ^0.6.1 - version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) + version: 0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2) '@nomicfoundation/hardhat-chai-matchers': specifier: ^2.0.7 version: 2.0.7(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(chai@4.4.1)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) chai: specifier: ^4.3.4 version: 4.4.1 @@ -369,13 +369,13 @@ importers: version: link:../../packages/hardhat-zksync-solc '@matterlabs/zksync-contracts': specifier: ^0.6.1 - version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) + version: 0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2) '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) chalk: specifier: ^4.1.2 version: 4.1.2 @@ -447,11 +447,11 @@ importers: specifier: 3.0.6 version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) '@openzeppelin/hardhat-upgrades': - specifier: ^2.5.1 - version: 2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + specifier: ^3.2.1 + version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) chalk: specifier: ^4.1.2 version: 4.1.2 @@ -469,8 +469,8 @@ importers: version: 6.8.0(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)) devDependencies: '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@types/node': specifier: ^18.11.17 version: 18.19.33 @@ -529,8 +529,8 @@ importers: specifier: 3.0.6 version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) chalk: specifier: ^4.1.2 version: 4.1.2 @@ -548,8 +548,8 @@ importers: version: 6.8.0(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)) devDependencies: '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@types/node': specifier: ^18.11.17 version: 18.19.33 @@ -859,7 +859,7 @@ importers: version: link:../hardhat-zksync-verify '@matterlabs/zksync-contracts': specifier: ^0.6.1 - version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) + version: 0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.4 version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) @@ -867,14 +867,14 @@ importers: specifier: ^2.0.0 version: 2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2 '@openzeppelin/contracts-upgradeable': - specifier: ^4.9.2 - version: 4.9.6 + specifier: ^5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) '@openzeppelin/upgrades-core': - specifier: ^1.31.3 - version: 1.33.1 + specifier: ^1.37.0 + version: 1.37.0 chai: specifier: ^4.3.4 version: 4.4.1 @@ -1337,17 +1337,23 @@ importers: specifier: ^3.0.6 version: 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts-hardhat-zksync-upgradable': - specifier: npm:@openzeppelin/contracts@^4.9.2 - version: '@openzeppelin/contracts@4.9.6' - '@openzeppelin/defender-admin-client': - specifier: ^1.52.0 - version: 1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10) + specifier: npm:@openzeppelin/contracts@^5.0.2 + version: '@openzeppelin/contracts@5.0.2' + '@openzeppelin/defender-sdk-base-client': + specifier: ^1.10.0 + version: 1.14.3 + '@openzeppelin/defender-sdk-deploy-client': + specifier: ^1.10.0 + version: 1.14.3(debug@4.3.5) + '@openzeppelin/defender-sdk-network-client': + specifier: ^1.10.0 + version: 1.14.3(debug@4.3.5) '@openzeppelin/hardhat-upgrades': - specifier: ~2.5.1 - version: 2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + specifier: ^3.2.1 + version: 3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/upgrades-core': - specifier: ^1.31.3 - version: 1.33.1 + specifier: ^1.37.0 + version: 1.37.0 chalk: specifier: ^4.1.2 version: 4.1.2 @@ -1848,9 +1854,6 @@ packages: '@ethersproject/base64@5.7.0': resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==, tarball: https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz} - '@ethersproject/basex@5.7.0': - resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==, tarball: https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz} - '@ethersproject/bignumber@5.7.0': resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==, tarball: https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz} @@ -1860,18 +1863,9 @@ packages: '@ethersproject/constants@5.7.0': resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==, tarball: https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz} - '@ethersproject/contracts@5.7.0': - resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==, tarball: https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz} - '@ethersproject/hash@5.7.0': resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==, tarball: https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz} - '@ethersproject/hdnode@5.7.0': - resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==, tarball: https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz} - - '@ethersproject/json-wallets@5.7.0': - resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==, tarball: https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz} - '@ethersproject/keccak256@5.7.0': resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==, tarball: https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz} @@ -1881,48 +1875,24 @@ packages: '@ethersproject/networks@5.7.1': resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==, tarball: https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz} - '@ethersproject/pbkdf2@5.7.0': - resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==, tarball: https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz} - '@ethersproject/properties@5.7.0': resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==, tarball: https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz} - '@ethersproject/providers@5.7.2': - resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==, tarball: https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz} - - '@ethersproject/random@5.7.0': - resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==, tarball: https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz} - '@ethersproject/rlp@5.7.0': resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==, tarball: https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz} - '@ethersproject/sha2@5.7.0': - resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==, tarball: https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz} - '@ethersproject/signing-key@5.7.0': resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==, tarball: https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz} - '@ethersproject/solidity@5.7.0': - resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==, tarball: https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz} - '@ethersproject/strings@5.7.0': resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==, tarball: https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz} '@ethersproject/transactions@5.7.0': resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==, tarball: https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz} - '@ethersproject/units@5.7.0': - resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==, tarball: https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz} - - '@ethersproject/wallet@5.7.0': - resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==, tarball: https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz} - '@ethersproject/web@5.7.1': resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==, tarball: https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz} - '@ethersproject/wordlists@5.7.0': - resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==, tarball: https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz} - '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==, tarball: https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz} engines: {node: '>=14'} @@ -2083,44 +2053,44 @@ packages: peerDependencies: hardhat: ^2.0.4 - '@nomicfoundation/slang-darwin-arm64@0.15.1': - resolution: {integrity: sha512-taPHlCUNNztQZJze9OlZFK9cZH8Ut4Ih4QJQo5CKebXx9vWOUtmSBfKv/M2P8hiV/iL7Q5sPwR7HY9uZYnb49Q==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.15.1.tgz} + '@nomicfoundation/slang-darwin-arm64@0.17.0': + resolution: {integrity: sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-darwin-x64@0.15.1': - resolution: {integrity: sha512-kgZh5KQe/UcbFqn1EpyrvBuT8E6I1kWSgGPtO25t90zAqFv23sMUPdn7wLpMjngkD+quIIgrzQGUtupS5YYEig==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.15.1.tgz} + '@nomicfoundation/slang-darwin-x64@0.17.0': + resolution: {integrity: sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-linux-arm64-gnu@0.15.1': - resolution: {integrity: sha512-Iw8mepaccKRWllPU9l+hoe88LN9fScC0Px3nFeNQy26qk1ueO0tjovP1dhTvmGwHUxacOYPqhQTUn7Iu0oxNoQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.15.1.tgz} + '@nomicfoundation/slang-linux-arm64-gnu@0.17.0': + resolution: {integrity: sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-linux-arm64-musl@0.15.1': - resolution: {integrity: sha512-zcesdQZwRgrT7ND+3TZUjRK/uGF20EfhEfCg8ZMhrb4Q7XaK1JvtHazIs03TV8Jcs30TPkEXks8Qi0Zdfy4RuA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.15.1.tgz} + '@nomicfoundation/slang-linux-arm64-musl@0.17.0': + resolution: {integrity: sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-linux-x64-gnu@0.15.1': - resolution: {integrity: sha512-FSmAnzKm58TFIwx4r/wOZtqfDx0nI6AfvnOh8kLDF5OxpWW3r0q9fq8lyaUReg9C/ZgCZRBn+m5WGrNKCZcvPQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.15.1.tgz} + '@nomicfoundation/slang-linux-x64-gnu@0.17.0': + resolution: {integrity: sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-linux-x64-musl@0.15.1': - resolution: {integrity: sha512-hnoA/dgeHQ8aS0SReABYkxf0d/Q6DdaKsaYv6ev21wyQA7TROxT1X3nekECLGu1GYLML8pzvD9vyAMBRKOkkyg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.15.1.tgz} + '@nomicfoundation/slang-linux-x64-musl@0.17.0': + resolution: {integrity: sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-win32-arm64-msvc@0.15.1': - resolution: {integrity: sha512-2H0chHQ4uTh4l4UxN5fIVHR5mKaL5mfYTID6kxxxv2+KAh68EpYWwxLlkS5So90R2WcuPvFvTVKLm/uRo4h4dg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.15.1.tgz} + '@nomicfoundation/slang-win32-arm64-msvc@0.17.0': + resolution: {integrity: sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-win32-ia32-msvc@0.15.1': - resolution: {integrity: sha512-CVZWBnbpFlVBg/m7bsiw70jY3p9TGH9vxq0vLEEJ56yK+QPosxPrKMcADojtGjIOjWjPSZ+lCoo5ilnW0a249g==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.15.1.tgz} + '@nomicfoundation/slang-win32-ia32-msvc@0.17.0': + resolution: {integrity: sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang-win32-x64-msvc@0.15.1': - resolution: {integrity: sha512-cyER8M1fdBTzIfihy55d4LGGlN/eQxDqfRUTXgJf1VvNR98tRB0Q3nBfyh5PK2yP98B4lMt3RJYDqTQu+dOVDA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.15.1.tgz} + '@nomicfoundation/slang-win32-x64-msvc@0.17.0': + resolution: {integrity: sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA==, tarball: https://registry.npmjs.org/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.17.0.tgz} engines: {node: '>= 10'} - '@nomicfoundation/slang@0.15.1': - resolution: {integrity: sha512-th7nxRWRXf583uHpWUCd8U7BYxIqJX2f3oZLff/mlPkqIr45pD2hLT/o00eCjrBIR8N7vybUULZg1CeThGNk7g==, tarball: https://registry.npmjs.org/@nomicfoundation/slang/-/slang-0.15.1.tgz} + '@nomicfoundation/slang@0.17.0': + resolution: {integrity: sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ==, tarball: https://registry.npmjs.org/@nomicfoundation/slang/-/slang-0.17.0.tgz} engines: {node: '>= 10'} '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': @@ -2199,19 +2169,13 @@ packages: resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==, tarball: https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@openzeppelin/contracts-upgradeable@4.9.6': - resolution: {integrity: sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz} - - '@openzeppelin/contracts@4.9.6': - resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz} - - '@openzeppelin/defender-admin-client@1.54.6': - resolution: {integrity: sha512-P4lxJDySrekWNuPa7FeyW/UmuxnuIXIAGYr5gZnmnMHRsYNaw+XfgkiCDfoGtjEyJbXYxXttYF6iAZhWQPdf1g==, tarball: https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.6.tgz} - deprecated: This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead. + '@openzeppelin/contracts-upgradeable@5.0.2': + resolution: {integrity: sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==, tarball: https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz} + peerDependencies: + '@openzeppelin/contracts': 5.0.2 - '@openzeppelin/defender-base-client@1.54.6': - resolution: {integrity: sha512-PTef+rMxkM5VQ7sLwLKSjp2DBakYQd661ZJiSRywx+q/nIpm3B/HYGcz5wPZCA5O/QcEP6TatXXDoeMwimbcnw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.6.tgz} - deprecated: This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead. + '@openzeppelin/contracts@5.0.2': + resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz} '@openzeppelin/defender-sdk-base-client@1.14.3': resolution: {integrity: sha512-4yG9E8N1c/ZP2jNR+Ah19wi7SBKpauAV/VcYcm7rg1dltDbzbH/oZnnXJlymT7IfjTPXkKHW8TPsaqz3EjS7tA==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.3.tgz} @@ -2219,24 +2183,23 @@ packages: '@openzeppelin/defender-sdk-deploy-client@1.14.3': resolution: {integrity: sha512-51WIZJz251lndK7uQU4gBE0gBX+2ZNTgf+hemtJUEPCpHtkooBRFFMID3EPGMKXVqf872pU8K3Huu9PyYQu6bw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.3.tgz} - '@openzeppelin/hardhat-upgrades@2.5.1': - resolution: {integrity: sha512-wRwq9f2PqlfIdNGFApsqRpqptqy98exSFp8SESb6Brgw4L07sExySInNJhscM/tWVSnR1Qnuws9Ck6Fs5zIxvg==, tarball: https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.5.1.tgz} + '@openzeppelin/defender-sdk-network-client@1.14.3': + resolution: {integrity: sha512-qrJLs2ubKSwrhP0x4V2QOPhlc1q8TYnkAcvjvk34VXMS8lhY1cpXSGoxnTw3Mi+eCSE1xOzKWISLi1UAOQOJIw==, tarball: https://registry.npmjs.org/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.14.3.tgz} + + '@openzeppelin/hardhat-upgrades@3.2.1': + resolution: {integrity: sha512-Zy5M3QhkzwGdpzQmk+xbWdYOGJWjoTvwbBKYLhctu9B91DoprlhDRaZUwCtunwTdynkTDGdVfGr0kIkvycyKjw==, tarball: https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.2.1.tgz} hasBin: true peerDependencies: '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-verify': ^1.1.0 + '@nomicfoundation/hardhat-verify': ^2.0.0 ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: '@nomicfoundation/hardhat-verify': optional: true - '@openzeppelin/upgrades-core@1.33.1': - resolution: {integrity: sha512-YRxIRhTY1b+j7+NUUu8Uuem5ugxKexEMVd8dBRWNgWeoN1gS1OCrhgUg0ytL+54vzQ+SGWZDfNnzjVuI1Cj1Zw==, tarball: https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.33.1.tgz} - hasBin: true - - '@openzeppelin/upgrades-core@1.35.0': - resolution: {integrity: sha512-XwwhJyPxACQ7rMhKAPCL6rhTXhbeumeQ3opmurEsHg025vHnISHwTPHd5VxzmOwbMBIJ7em1lnRTu+J2/IUWFQ==, tarball: https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.35.0.tgz} + '@openzeppelin/upgrades-core@1.37.0': + resolution: {integrity: sha512-vpxe60KrbFubY09vlGZqBJdBXs0IqvZmH7+UueFiM0xK/V12lMwxyiNXkFv8+HZ7K8abRevYphVtEzrUWelQhQ==, tarball: https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.37.0.tgz} hasBin: true '@pkgjs/parseargs@0.11.0': @@ -2573,9 +2536,6 @@ packages: resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==, tarball: https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz} engines: {node: '>=0.3.0'} - aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==, tarball: https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz} - aes-js@4.0.0-beta.5: resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==, tarball: https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz} @@ -2730,9 +2690,6 @@ packages: bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==, tarball: https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz} - bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==, tarball: https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz} - better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==, tarball: https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz} engines: {node: '>=4'} @@ -3389,9 +3346,6 @@ packages: resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==, tarball: https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz} engines: {node: '>=10.0.0'} - ethers@5.7.2: - resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==, tarball: https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz} - ethers@6.12.2: resolution: {integrity: sha512-MNfR2kzZyNF8bRNDSmjM+rT1+yqCgYNqfrXyNnpiNId2MQPiAOOr/7lrgdrdwoBxzKPSnSYZaGb5lcNyvzhuvA==, tarball: https://registry.npmjs.org/ethers/-/ethers-6.12.2.tgz} engines: {node: '>=14.0.0'} @@ -4113,6 +4067,10 @@ packages: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==, tarball: https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz} engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==, tarball: https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz} + engines: {node: '>=16 || 14 >=14.17'} + minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==, tarball: https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz} engines: {node: '>= 6'} @@ -5108,18 +5066,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, tarball: https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz} - ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==, tarball: https://registry.npmjs.org/ws/-/ws-7.4.6.tgz} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==, tarball: https://registry.npmjs.org/ws/-/ws-7.5.9.tgz} engines: {node: '>=8.3.0'} @@ -5496,11 +5442,6 @@ snapshots: dependencies: '@ethersproject/bytes': 5.7.0 - '@ethersproject/basex@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/bignumber@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5515,19 +5456,6 @@ snapshots: dependencies: '@ethersproject/bignumber': 5.7.0 - '@ethersproject/contracts@5.7.0': - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/hash@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 @@ -5540,37 +5468,6 @@ snapshots: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - '@ethersproject/hdnode@5.7.0': - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - - '@ethersproject/json-wallets@5.7.0': - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - '@ethersproject/keccak256@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5582,57 +5479,15 @@ snapshots: dependencies: '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/properties@5.7.0': dependencies: '@ethersproject/logger': 5.7.0 - '@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)': - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - bech32: 1.1.4 - ws: 7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@ethersproject/random@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 - '@ethersproject/sha2@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - hash.js: 1.1.7 - '@ethersproject/signing-key@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5642,15 +5497,6 @@ snapshots: elliptic: 6.5.4 hash.js: 1.1.7 - '@ethersproject/solidity@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/strings@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 @@ -5669,30 +5515,6 @@ snapshots: '@ethersproject/rlp': 5.7.0 '@ethersproject/signing-key': 5.7.0 - '@ethersproject/units@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - - '@ethersproject/wallet@5.7.0': - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - '@ethersproject/web@5.7.1': dependencies: '@ethersproject/base64': 5.7.0 @@ -5701,14 +5523,6 @@ snapshots: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - '@ethersproject/wordlists@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@fastify/busboy@2.1.1': {} '@humanwhocodes/config-array@0.11.14': @@ -5770,10 +5584,10 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@matterlabs/zksync-contracts@0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6)': + '@matterlabs/zksync-contracts@0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2)': dependencies: - '@openzeppelin/contracts': 4.9.6 - '@openzeppelin/contracts-upgradeable': 4.9.6 + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) '@metamask/eth-sig-util@4.0.1': dependencies: @@ -5884,35 +5698,35 @@ snapshots: transitivePeerDependencies: - supports-color - '@nomicfoundation/slang-darwin-arm64@0.15.1': {} + '@nomicfoundation/slang-darwin-arm64@0.17.0': {} - '@nomicfoundation/slang-darwin-x64@0.15.1': {} + '@nomicfoundation/slang-darwin-x64@0.17.0': {} - '@nomicfoundation/slang-linux-arm64-gnu@0.15.1': {} + '@nomicfoundation/slang-linux-arm64-gnu@0.17.0': {} - '@nomicfoundation/slang-linux-arm64-musl@0.15.1': {} + '@nomicfoundation/slang-linux-arm64-musl@0.17.0': {} - '@nomicfoundation/slang-linux-x64-gnu@0.15.1': {} + '@nomicfoundation/slang-linux-x64-gnu@0.17.0': {} - '@nomicfoundation/slang-linux-x64-musl@0.15.1': {} + '@nomicfoundation/slang-linux-x64-musl@0.17.0': {} - '@nomicfoundation/slang-win32-arm64-msvc@0.15.1': {} + '@nomicfoundation/slang-win32-arm64-msvc@0.17.0': {} - '@nomicfoundation/slang-win32-ia32-msvc@0.15.1': {} + '@nomicfoundation/slang-win32-ia32-msvc@0.17.0': {} - '@nomicfoundation/slang-win32-x64-msvc@0.15.1': {} + '@nomicfoundation/slang-win32-x64-msvc@0.17.0': {} - '@nomicfoundation/slang@0.15.1': + '@nomicfoundation/slang@0.17.0': dependencies: - '@nomicfoundation/slang-darwin-arm64': 0.15.1 - '@nomicfoundation/slang-darwin-x64': 0.15.1 - '@nomicfoundation/slang-linux-arm64-gnu': 0.15.1 - '@nomicfoundation/slang-linux-arm64-musl': 0.15.1 - '@nomicfoundation/slang-linux-x64-gnu': 0.15.1 - '@nomicfoundation/slang-linux-x64-musl': 0.15.1 - '@nomicfoundation/slang-win32-arm64-msvc': 0.15.1 - '@nomicfoundation/slang-win32-ia32-msvc': 0.15.1 - '@nomicfoundation/slang-win32-x64-msvc': 0.15.1 + '@nomicfoundation/slang-darwin-arm64': 0.17.0 + '@nomicfoundation/slang-darwin-x64': 0.17.0 + '@nomicfoundation/slang-linux-arm64-gnu': 0.17.0 + '@nomicfoundation/slang-linux-arm64-musl': 0.17.0 + '@nomicfoundation/slang-linux-x64-gnu': 0.17.0 + '@nomicfoundation/slang-linux-x64-musl': 0.17.0 + '@nomicfoundation/slang-win32-arm64-msvc': 0.17.0 + '@nomicfoundation/slang-win32-ia32-msvc': 0.17.0 + '@nomicfoundation/slang-win32-x64-msvc': 0.17.0 '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': optional: true @@ -5981,42 +5795,29 @@ snapshots: dependencies: which: 3.0.1 - '@openzeppelin/contracts-upgradeable@4.9.6': {} + '@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2)': + dependencies: + '@openzeppelin/contracts': 5.0.2 - '@openzeppelin/contracts@4.9.6': {} + '@openzeppelin/contracts@5.0.2': {} - '@openzeppelin/defender-admin-client@1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10)': + '@openzeppelin/defender-sdk-base-client@1.14.3': dependencies: - '@openzeppelin/defender-base-client': 1.54.6(debug@4.3.5) - axios: 1.7.2(debug@4.3.5) - ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - lodash: 4.17.21 - node-fetch: 2.7.0 + amazon-cognito-identity-js: 6.3.12 + async-retry: 1.3.3 transitivePeerDependencies: - - bufferutil - - debug - encoding - - utf-8-validate - '@openzeppelin/defender-base-client@1.54.6(debug@4.3.5)': + '@openzeppelin/defender-sdk-deploy-client@1.14.3(debug@4.3.5)': dependencies: - amazon-cognito-identity-js: 6.3.12 - async-retry: 1.3.3 + '@openzeppelin/defender-sdk-base-client': 1.14.3 axios: 1.7.2(debug@4.3.5) lodash: 4.17.21 - node-fetch: 2.7.0 transitivePeerDependencies: - debug - encoding - '@openzeppelin/defender-sdk-base-client@1.14.3': - dependencies: - amazon-cognito-identity-js: 6.3.12 - async-retry: 1.3.3 - transitivePeerDependencies: - - encoding - - '@openzeppelin/defender-sdk-deploy-client@1.14.3(debug@4.3.5)': + '@openzeppelin/defender-sdk-network-client@1.14.3(debug@4.3.5)': dependencies: '@openzeppelin/defender-sdk-base-client': 1.14.3 axios: 1.7.2(debug@4.3.5) @@ -6025,48 +5826,35 @@ snapshots: - debug - encoding - '@openzeppelin/hardhat-upgrades@2.5.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(bufferutil@4.0.8)(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10)': + '@openzeppelin/hardhat-upgrades@3.2.1(@nomicfoundation/hardhat-ethers@3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-verify@2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@nomicfoundation/hardhat-ethers': 3.0.6(ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) - '@openzeppelin/defender-admin-client': 1.54.6(bufferutil@4.0.8)(debug@4.3.5)(utf-8-validate@5.0.10) - '@openzeppelin/defender-base-client': 1.54.6(debug@4.3.5) '@openzeppelin/defender-sdk-base-client': 1.14.3 '@openzeppelin/defender-sdk-deploy-client': 1.14.3(debug@4.3.5) - '@openzeppelin/upgrades-core': 1.35.0 + '@openzeppelin/defender-sdk-network-client': 1.14.3(debug@4.3.5) + '@openzeppelin/upgrades-core': 1.37.0 chalk: 4.1.2 debug: 4.3.5 ethereumjs-util: 7.1.5 ethers: 6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat: 2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) proper-lockfile: 4.1.2 - undici: 5.28.4 + undici: 6.18.2 + optionalDependencies: + '@nomicfoundation/hardhat-verify': 2.0.8(hardhat@2.22.5(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@18.19.33)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) transitivePeerDependencies: - - bufferutil - encoding - supports-color - - utf-8-validate - - '@openzeppelin/upgrades-core@1.33.1': - dependencies: - cbor: 9.0.2 - chalk: 4.1.2 - compare-versions: 6.1.0 - debug: 4.3.5 - ethereumjs-util: 7.1.5 - minimist: 1.2.8 - proper-lockfile: 4.1.2 - solidity-ast: 0.4.56 - transitivePeerDependencies: - - supports-color - '@openzeppelin/upgrades-core@1.35.0': + '@openzeppelin/upgrades-core@1.37.0': dependencies: - '@nomicfoundation/slang': 0.15.1 + '@nomicfoundation/slang': 0.17.0 cbor: 9.0.2 chalk: 4.1.2 compare-versions: 6.1.0 debug: 4.3.5 ethereumjs-util: 7.1.5 + minimatch: 9.0.5 minimist: 1.2.8 proper-lockfile: 4.1.2 solidity-ast: 0.4.56 @@ -6485,8 +6273,6 @@ snapshots: adm-zip@0.4.16: {} - aes-js@3.0.0: {} - aes-js@4.0.0-beta.5: {} agent-base@6.0.2: @@ -6676,8 +6462,6 @@ snapshots: dependencies: tweetnacl: 0.14.5 - bech32@1.1.4: {} - better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -7582,42 +7366,6 @@ snapshots: ethereum-cryptography: 0.1.3 rlp: 2.2.7 - ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/contracts': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/solidity': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/units': 5.7.0 - '@ethersproject/wallet': 5.7.0 - '@ethersproject/web': 5.7.1 - '@ethersproject/wordlists': 5.7.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - ethers@6.12.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: '@adraffy/ens-normalize': 1.10.1 @@ -8412,6 +8160,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + minimist-options@4.1.0: dependencies: arrify: 1.0.1 @@ -9470,11 +9222,6 @@ snapshots: wrappy@1.0.2: {} - ws@7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 5.0.10 - ws@7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10): optionalDependencies: bufferutil: 4.0.8 From bc4368a4517d6485d9c9aee6d5c178f8cfc7e163 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 4 Sep 2024 09:55:02 +0200 Subject: [PATCH 15/20] fix: revert oz contracts for basic example and update readme file --- examples/basic-example/package.json | 4 +-- packages/hardhat-zksync-upgradable/README.md | 27 +++++++++++++++++--- pnpm-lock.yaml | 25 ++++++++++++++---- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/examples/basic-example/package.json b/examples/basic-example/package.json index 0eb0e33c8..cb0e5e4b1 100644 --- a/examples/basic-example/package.json +++ b/examples/basic-example/package.json @@ -36,8 +36,8 @@ "ethers": "^6.12.2", "zksync-ethers": "^6.8.0", "@matterlabs/zksync-contracts": "^0.6.1", - "@openzeppelin/contracts": "^5.0.2", - "@openzeppelin/contracts-upgradeable": "^5.0.2" + "@openzeppelin/contracts": "^4.9.6", + "@openzeppelin/contracts-upgradeable": "^4.9.6" }, "prettier": { "tabWidth": 4, diff --git a/packages/hardhat-zksync-upgradable/README.md b/packages/hardhat-zksync-upgradable/README.md index 28adc738b..4c06943a1 100644 --- a/packages/hardhat-zksync-upgradable/README.md +++ b/packages/hardhat-zksync-upgradable/README.md @@ -84,6 +84,16 @@ The UUPS proxy pattern is similar to the transparent proxy pattern, except that To deploy the UUPS contract, use the same script as for the transparent upgradable proxy. When you run the script, the plugin detects that the proxy type is UUPS, it executes the deployment, and saves the deployment info in your manifest file. +In OpenZeppelin Contracts 5.0, the UUPS (Upgradeable Proxy Pattern) proxy contract indeed allows for unsafe state-variable-assignment. By passing ['state-variable-assignment'] in the options section during deployment, you indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. + +``` +await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [initializerFunctionArguments], + { initializer: "initialize", + unsafeAllow: ['state-variable-assignment'] + } +); +``` + - **Beacon proxies** Beacon proxies enable a more advanced upgrade pattern, where multiple implementation contracts can be deployed and "hot-swapped" on the fly with no disruption to the contract's operation. @@ -170,6 +180,15 @@ await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, , myContract Similar to the deployment script, there are no modifications needed to upgrade the implementation of the UUPS contract, compared to upgrading the transparent upgradable contract. +In OpenZeppelin Contracts 5.0, the UUPS (Upgradeable Proxy Pattern) proxy contract indeed allows for unsafe state-variable-assignment. By passing ['state-variable-assignment'] in the options section during upgrade, you indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. + +``` +await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, , myContractV2, { + unsafeAllow: ['state-variable-assignment'] + } +); +``` + - **Upgrade beacon proxy** Beacon proxy implementation can be upgraded using a similarly structured method from the zkUpgrades called upgradeBeacon @@ -282,18 +301,18 @@ const config: HardhatUserConfig = { ### 🕹 Command list -`yarn hardhat deploy-zksync:proxy --contract-name [] [--constructor-args ] [--initializer ] [--no-compile] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ]` +`yarn hardhat deploy-zksync:proxy --contract-name [] [--constructor-args ] [--initializer ] [--no-compile] [--initial-owner ] [--unsafe-state-varaible-assignment] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ]` When executed, this command will automatically determine whether the deployment is for a Transparent or UUPS proxy. If the Transparent proxy is chosen, it will deploy implementation, admin, and proxy. If the UUPS proxy is chosen, it will deploy implementation and proxy. -`yarn hardhat upgrade-zksync:proxy --contract-name --proxy-address [--deployment-type ] [--salt ] [--no-compile]` +`yarn hardhat upgrade-zksync:proxy --contract-name --proxy-address [--deployment-type ] [--salt ] [--unsafe-state-varaible-assignment] [--no-compile]` When executed, this command upgrade UUPS or Transparent implementation. To upgrade a implementation we need to specify proxy address, add `--proxy-address ` argument, e.g. `yarn hardhat upgrade-zksync:proxy --contract-name BoxV2 --proxy-address 0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520`. -`yarn hardhat deploy-zksync:beacon --contract-name [] [--constructor-args ] [--initializer ] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ] [--no-compile]` +`yarn hardhat deploy-zksync:beacon --contract-name [] [--constructor-args ] [--initializer ] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ] [--initial-owner ] [--no-compile]` When executed, this command deploys the provided implementation, beacon and proxy on the specified network, using the provided contract constructor arguments. @@ -319,6 +338,8 @@ module.exports = [ ``` - To provide a initializer method name at deploy tasks, add `--initializer `, e.g. `hardhat deploy-zksync:proxy --contract-name Contract --initializer store`. If this parameter is omitted, the default value will be `initialize`. - To allows the task to skip the compilation process, add `--no-compile` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Contract --no-compile`. +- To specify inital contract owner, add `--initial-owner` argument, e.g `hardhat deploy-zksync:beacon --contract-name Contract --initial-owner 0xa61464658AfeAf65CccaaFD3a512b69A83B77618`. If this argument is ommited wallet address will be used. +- To specify unsafe state-variable-assignment, add `--unsafe-state-variable-assignment` flag, e.g `hardhat deploy-zksync:proxy --contract-name Contract --initializer store --unsafe-state-variable-assignment`. In OpenZeppelin Contracts 5.0 this flag is mandatory and indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. - To allows the task to specify which deployer smart contract function will be called for implementation, add `--deployment-type-impl` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --deployment-type-impl create2`. - To allows the task to specify which deployer smart contract function will be called for proxy, add `--deployment-type-proxy` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --deployment-type-proxy create2`. - To specify which salt will be used in deployment of the implementation, add `--salt-impl` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --salt-impl 0x42737956734178574166864921632769419836642485081335718122152413290` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95ad7521c..a67e83744 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,13 +43,13 @@ importers: version: link:../../packages/hardhat-zksync-solc '@matterlabs/zksync-contracts': specifier: ^0.6.1 - version: 0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2) + version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) '@openzeppelin/contracts': - specifier: ^5.0.2 - version: 5.0.2 + specifier: ^4.9.6 + version: 4.9.6 '@openzeppelin/contracts-upgradeable': - specifier: ^5.0.2 - version: 5.0.2(@openzeppelin/contracts@5.0.2) + specifier: ^4.9.6 + version: 4.9.6 chalk: specifier: ^4.1.2 version: 4.1.2 @@ -2169,11 +2169,17 @@ packages: resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==, tarball: https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@openzeppelin/contracts-upgradeable@4.9.6': + resolution: {integrity: sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz} + '@openzeppelin/contracts-upgradeable@5.0.2': resolution: {integrity: sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==, tarball: https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz} peerDependencies: '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts@4.9.6': + resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz} + '@openzeppelin/contracts@5.0.2': resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==, tarball: https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz} @@ -5584,6 +5590,11 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@matterlabs/zksync-contracts@0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6)': + dependencies: + '@openzeppelin/contracts': 4.9.6 + '@openzeppelin/contracts-upgradeable': 4.9.6 + '@matterlabs/zksync-contracts@0.6.1(@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2))(@openzeppelin/contracts@5.0.2)': dependencies: '@openzeppelin/contracts': 5.0.2 @@ -5795,10 +5806,14 @@ snapshots: dependencies: which: 3.0.1 + '@openzeppelin/contracts-upgradeable@4.9.6': {} + '@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2)': dependencies: '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts@4.9.6': {} + '@openzeppelin/contracts@5.0.2': {} '@openzeppelin/defender-sdk-base-client@1.14.3': From 50b46c14ac4baeea4414996b175abab7a07bf93a Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 4 Sep 2024 12:36:43 +0200 Subject: [PATCH 16/20] fix: revert manifest and storage layout --- .../src/validations/validate-impl.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts b/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts index dec3dac25..c56671822 100644 --- a/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts +++ b/packages/hardhat-zksync-upgradable/src/validations/validate-impl.ts @@ -4,12 +4,12 @@ import { assertUpgradeSafe, getImplementationAddress, getImplementationAddressFromBeacon, - getStorageLayoutForAddress, - Manifest, - processProxyKind, ValidationOptions, } from '@openzeppelin/upgrades-core'; +import { getStorageLayoutForAddress } from '../core/manifest-storage-layout'; +import { Manifest } from '../core/manifest'; import { DeployData } from '../proxy-deployment/deploy-impl'; +import { processProxyKind } from '../core/proxy-kind'; /** * Processes the proxy kind and returns the implementation address if proxyAddress is provided. From 58815f749be81bc7e7ac458e4a163cfaa5fc215a Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Mon, 9 Sep 2024 13:51:56 +0200 Subject: [PATCH 17/20] fix: remove unsafeAllow for uups proxies --- .../scripts/deploy-box-uups.ts | 2 +- .../scripts/upgrade-box-uups.ts | 2 +- .../scripts/deploy-box-uups-factory.ts | 2 +- .../scripts/deploy-box-uups.ts | 4 ++-- .../scripts/upgrade-box-uups.ts | 4 ++-- packages/hardhat-zksync-upgradable/README.md | 24 ++----------------- .../hardhat-zksync-upgradable/src/index.ts | 8 ------- .../hardhat-zksync-upgradable/src/plugin.ts | 3 --- .../hardhat-zksync-upgradable/test/tests.ts | 16 +------------ 9 files changed, 10 insertions(+), 55 deletions(-) diff --git a/examples/upgradable-example-l1/scripts/deploy-box-uups.ts b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts index 49fc4dd15..553ac7039 100644 --- a/examples/upgradable-example-l1/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example-l1/scripts/deploy-box-uups.ts @@ -2,7 +2,7 @@ import * as hre from 'hardhat'; async function main() { const Box = await hre.ethers.getContractFactory("BoxUups"); - const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize' }); await box.waitForDeployment() console.info("Box deployed address: " + await box.getAddress()) } diff --git a/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts index d107ff162..72aef9544 100644 --- a/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example-l1/scripts/upgrade-box-uups.ts @@ -2,7 +2,7 @@ import * as hre from 'hardhat'; async function main() { const Box = await hre.ethers.getContractFactory("BoxUups"); - const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); + const box = await hre.upgrades.deployProxy(Box,[42],{ initializer: 'initialize' }); await box.waitForDeployment() console.info("Box deployed address: " + await box.getAddress()) diff --git a/examples/upgradable-example/scripts/deploy-box-uups-factory.ts b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts index 14d99405b..60e83b649 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups-factory.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups-factory.ts @@ -14,7 +14,7 @@ async function main() { const deployer = new Deployer(hre, zkWallet); const boxFactory = await hre.zksyncEthers.getContractFactory('BoxUups', deployer.zkWallet); - const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment']}); + const box = await hre.upgrades.deployProxy(boxFactory, [42], { initializer: 'initialize' }); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/deploy-box-uups.ts b/examples/upgradable-example/scripts/deploy-box-uups.ts index a1d50cc5c..53b38e32f 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups.ts @@ -9,12 +9,12 @@ async function main() { console.info(chalk.yellow(`Deploying ${contractName}...`)); const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; - const zkWallet = Wallet.fromMnemonic(testMnemonic); + const zkWallet = new Wallet('0x9d81dd1aaccd4bd613a641e42728ccfa49aaf5c0eda8ce5faeb159c493894329') const deployer = new Deployer(hre, zkWallet); const contract = await deployer.loadArtifact(contractName); - const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment'] }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize'}); await box.waitForDeployment(); diff --git a/examples/upgradable-example/scripts/upgrade-box-uups.ts b/examples/upgradable-example/scripts/upgrade-box-uups.ts index d7ddc709e..364d8517f 100644 --- a/examples/upgradable-example/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example/scripts/upgrade-box-uups.ts @@ -6,14 +6,14 @@ import * as hre from 'hardhat'; async function main() { const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; - const zkWallet = Wallet.fromMnemonic(testMnemonic); + const zkWallet = new Wallet('0x9d81dd1aaccd4bd613a641e42728ccfa49aaf5c0eda8ce5faeb159c493894329') const deployer = new Deployer(hre, zkWallet); // deploy proxy const contractName = 'BoxUups'; const contract = await deployer.loadArtifact(contractName); - const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize', unsafeAllow: ['state-variable-assignment'] }); + const box = await hre.upgrades.deployProxy(deployer.zkWallet, contract, [42], { initializer: 'initialize' }); await box.waitForDeployment(); diff --git a/packages/hardhat-zksync-upgradable/README.md b/packages/hardhat-zksync-upgradable/README.md index 4c06943a1..3b61cc8c6 100644 --- a/packages/hardhat-zksync-upgradable/README.md +++ b/packages/hardhat-zksync-upgradable/README.md @@ -84,16 +84,6 @@ The UUPS proxy pattern is similar to the transparent proxy pattern, except that To deploy the UUPS contract, use the same script as for the transparent upgradable proxy. When you run the script, the plugin detects that the proxy type is UUPS, it executes the deployment, and saves the deployment info in your manifest file. -In OpenZeppelin Contracts 5.0, the UUPS (Upgradeable Proxy Pattern) proxy contract indeed allows for unsafe state-variable-assignment. By passing ['state-variable-assignment'] in the options section during deployment, you indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. - -``` -await hre.zkUpgrades.deployProxy(deployer.zkWallet, contract, [initializerFunctionArguments], - { initializer: "initialize", - unsafeAllow: ['state-variable-assignment'] - } -); -``` - - **Beacon proxies** Beacon proxies enable a more advanced upgrade pattern, where multiple implementation contracts can be deployed and "hot-swapped" on the fly with no disruption to the contract's operation. @@ -180,15 +170,6 @@ await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, , myContract Similar to the deployment script, there are no modifications needed to upgrade the implementation of the UUPS contract, compared to upgrading the transparent upgradable contract. -In OpenZeppelin Contracts 5.0, the UUPS (Upgradeable Proxy Pattern) proxy contract indeed allows for unsafe state-variable-assignment. By passing ['state-variable-assignment'] in the options section during upgrade, you indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. - -``` -await hre.zkUpgrades.upgradeProxy(deployer.zkWallet, , myContractV2, { - unsafeAllow: ['state-variable-assignment'] - } -); -``` - - **Upgrade beacon proxy** Beacon proxy implementation can be upgraded using a similarly structured method from the zkUpgrades called upgradeBeacon @@ -301,13 +282,13 @@ const config: HardhatUserConfig = { ### 🕹 Command list -`yarn hardhat deploy-zksync:proxy --contract-name [] [--constructor-args ] [--initializer ] [--no-compile] [--initial-owner ] [--unsafe-state-varaible-assignment] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ]` +`yarn hardhat deploy-zksync:proxy --contract-name [] [--constructor-args ] [--initializer ] [--no-compile] [--initial-owner ] [--deployment-type-impl ] [--salt-impl ] [--deployment-type-proxy ] [--salt-proxy ]` When executed, this command will automatically determine whether the deployment is for a Transparent or UUPS proxy. If the Transparent proxy is chosen, it will deploy implementation, admin, and proxy. If the UUPS proxy is chosen, it will deploy implementation and proxy. -`yarn hardhat upgrade-zksync:proxy --contract-name --proxy-address [--deployment-type ] [--salt ] [--unsafe-state-varaible-assignment] [--no-compile]` +`yarn hardhat upgrade-zksync:proxy --contract-name --proxy-address [--deployment-type ] [--salt ] [--no-compile]` When executed, this command upgrade UUPS or Transparent implementation. To upgrade a implementation we need to specify proxy address, add `--proxy-address ` argument, e.g. `yarn hardhat upgrade-zksync:proxy --contract-name BoxV2 --proxy-address 0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520`. @@ -339,7 +320,6 @@ module.exports = [ - To provide a initializer method name at deploy tasks, add `--initializer `, e.g. `hardhat deploy-zksync:proxy --contract-name Contract --initializer store`. If this parameter is omitted, the default value will be `initialize`. - To allows the task to skip the compilation process, add `--no-compile` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Contract --no-compile`. - To specify inital contract owner, add `--initial-owner` argument, e.g `hardhat deploy-zksync:beacon --contract-name Contract --initial-owner 0xa61464658AfeAf65CccaaFD3a512b69A83B77618`. If this argument is ommited wallet address will be used. -- To specify unsafe state-variable-assignment, add `--unsafe-state-variable-assignment` flag, e.g `hardhat deploy-zksync:proxy --contract-name Contract --initializer store --unsafe-state-variable-assignment`. In OpenZeppelin Contracts 5.0 this flag is mandatory and indicate that you are aware of the risks associated with direct state variable assignments in upgradeable contracts. - To allows the task to specify which deployer smart contract function will be called for implementation, add `--deployment-type-impl` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --deployment-type-impl create2`. - To allows the task to specify which deployer smart contract function will be called for proxy, add `--deployment-type-proxy` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --deployment-type-proxy create2`. - To specify which salt will be used in deployment of the implementation, add `--salt-impl` argument, e.g. `hardhat deploy-zksync:beacon --contract-name Greeter 'Hello' --salt-impl 0x42737956734178574166864921632769419836642485081335718122152413290` diff --git a/packages/hardhat-zksync-upgradable/src/index.ts b/packages/hardhat-zksync-upgradable/src/index.ts index ff7b6fb3d..101ce741f 100644 --- a/packages/hardhat-zksync-upgradable/src/index.ts +++ b/packages/hardhat-zksync-upgradable/src/index.ts @@ -65,10 +65,6 @@ task(TASK_DEPLOY_ZKSYNC_PROXY, 'Deploy proxy for ZKsync network') .addOptionalParam('saltImpl', 'Salt for implementation deployment', undefined) .addOptionalParam('saltProxy', 'Salt for proxy deployment', undefined) .addOptionalParam('initialOwner', 'Initial owner of the proxy', undefined) - .addFlag( - 'unsafeStateVariableAssignment', - 'Allow unsafe state-variable-assignment. This flag is mandatory for uups proxy deployment.', - ) .addFlag('noCompile', 'No compile flag') .setAction(deployZkSyncProxy); @@ -85,10 +81,6 @@ task(TASK_UPGRADE_ZKSYNC_PROXY, 'Runs the proxy upgrade for ZKsync network') .addParam('proxyAddress', 'Proxy address of the deployed contract', '') .addOptionalParam('deploymentType', 'Type of deployment', undefined) .addOptionalParam('salt', 'Salt for deployment', undefined) - .addFlag( - 'unsafeStateVariableAssignment', - 'Allow unsafe state-variable-assignment. This flag is mandatory for uups proxy upgrade.', - ) .addFlag('noCompile', 'No compile flag') .setAction(upgradeZkSyncProxy); diff --git a/packages/hardhat-zksync-upgradable/src/plugin.ts b/packages/hardhat-zksync-upgradable/src/plugin.ts index afc0bee64..5f8c26aaa 100644 --- a/packages/hardhat-zksync-upgradable/src/plugin.ts +++ b/packages/hardhat-zksync-upgradable/src/plugin.ts @@ -76,7 +76,6 @@ export async function deployProxy( saltImpl?: string; saltProxy?: string; initialOwner?: string; - unsafeStateVariableAssignment?: boolean; noCompile?: boolean; }, ): Promise { @@ -101,7 +100,6 @@ export async function deployProxy( saltProxy: taskArgs.saltProxy, initializer: taskArgs.initializer, initialOwner: taskArgs.initialOwner, - unsafeAllow: taskArgs.unsafeStateVariableAssignment ? ['state-variable-assignment'] : undefined, }); await proxy.waitForDeployment(); @@ -161,7 +159,6 @@ export async function upgradeProxy( const proxyUpgrade = await hre.upgrades.upgradeProxy(wallet, taskArgs.proxyAddress, contractV2, { deploymentType: taskArgs.deploymentType, salt: taskArgs.salt, - unsafeAllow: taskArgs.unsafeStateVariableAssignment ? ['state-variable-assignment'] : undefined, }); await proxyUpgrade.waitForDeployment(); diff --git a/packages/hardhat-zksync-upgradable/test/tests.ts b/packages/hardhat-zksync-upgradable/test/tests.ts index 0100f0d2b..acfe2d2be 100644 --- a/packages/hardhat-zksync-upgradable/test/tests.ts +++ b/packages/hardhat-zksync-upgradable/test/tests.ts @@ -90,7 +90,6 @@ describe('Upgradable plugin tests', function () { const boxArtifact = await this.deployer.loadArtifact(contractName1); boxUupsProxy = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, boxArtifact, [42], { initializer: 'initialize', - unsafeAllow: ['state-variable-assignment'], }); await boxUupsProxy.waitForDeployment(); @@ -103,7 +102,6 @@ describe('Upgradable plugin tests', function () { [42], { initializer: 'initialize', - unsafeAllow: ['state-variable-assignment'], }, ); await boxUupsPublicProxy.waitForDeployment(); @@ -128,9 +126,6 @@ describe('Upgradable plugin tests', function () { this.deployer.zkWallet, await boxUupsProxy.getAddress(), BoxV2, - { - unsafeAllow: ['state-variable-assignment'], - }, ); await new Promise((resolve) => setTimeout(resolve, 1500)); box2.connect(this.deployer.zkWallet); @@ -144,9 +139,7 @@ describe('Upgradable plugin tests', function () { const BoxV2 = await this.deployer.loadArtifact(contractName); await assert.rejects( - this.env.zkUpgrades.upgradeProxy(this.zkWallet2, await boxUupsProxy.getAddress(), BoxV2, { - unsafeAllow: ['state-variable-assignment'], - }), + this.env.zkUpgrades.upgradeProxy(this.zkWallet2, await boxUupsProxy.getAddress(), BoxV2), ); }); @@ -160,9 +153,6 @@ describe('Upgradable plugin tests', function () { this.zkWallet2, await boxUupsPublicProxy.getAddress(), BoxV2, - { - unsafeAllow: ['state-variable-assignment'], - }, ); await box2.waitForDeployment(); console.info(chalk.green('Successfully upgraded BoxUupsPublic to BoxUupsV2')); @@ -183,7 +173,6 @@ describe('Upgradable plugin tests', function () { this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', kind: 'uups', - unsafeAllow: ['state-variable-assignment'], }), (error: any) => error.message.includes(standaloneValidationErrors.MISSING_PUBLIC_UPGRADE_TO), ); @@ -198,7 +187,6 @@ describe('Upgradable plugin tests', function () { await assert.rejects( this.env.zkUpgrades.upgradeProxy(this.deployer.zkWallet, await boxUupsProxy.getAddress(), boxV2, { kind: 'uups', - unsafeAllow: ['state-variable-assignment'], }), (error: any) => error.message.includes(standaloneValidationErrors.MISSING_PUBLIC_UPGRADE_TO) && @@ -520,7 +508,6 @@ describe('Upgradable plugin tests', function () { const box = await this.env.zkUpgrades.deployProxy(this.deployer.zkWallet, contract, [42], { initializer: 'initialize', kind: 'uups', - unsafeAllow: ['state-variable-assignment'], }); await box.waitForDeployment(); @@ -606,7 +593,6 @@ describe('Test for upgrades for shortcuts commands', function () { const box = await deployProxy(this.env, { contractName: 'BoxUups', constructorArgsParams: [42], - unsafeStateVariableAssignment: true, }); const value = await box.retrieve(); From 93a11bab16589acc2c5b26b38fa2d72817d219da Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Mon, 9 Sep 2024 13:57:24 +0200 Subject: [PATCH 18/20] chore: remove only from tests --- packages/hardhat-zksync-upgradable/test/tests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hardhat-zksync-upgradable/test/tests.ts b/packages/hardhat-zksync-upgradable/test/tests.ts index acfe2d2be..af67a9716 100644 --- a/packages/hardhat-zksync-upgradable/test/tests.ts +++ b/packages/hardhat-zksync-upgradable/test/tests.ts @@ -309,7 +309,7 @@ describe('Upgradable plugin tests', function () { ); }); - it.only('Should fail to change the admin - wrong signer', async function () { + it('Should fail to change the admin - wrong signer', async function () { const contractName = 'Box'; console.info(chalk.yellow(`Deploying ${contractName}...`)); From 80956154fc753e4fa0cb43bd0b7e9412d349d31c Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Mon, 9 Sep 2024 14:18:16 +0200 Subject: [PATCH 19/20] chore: revert a mnemonic --- examples/upgradable-example/scripts/upgrade-box-uups.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/upgradable-example/scripts/upgrade-box-uups.ts b/examples/upgradable-example/scripts/upgrade-box-uups.ts index 364d8517f..c259ace14 100644 --- a/examples/upgradable-example/scripts/upgrade-box-uups.ts +++ b/examples/upgradable-example/scripts/upgrade-box-uups.ts @@ -6,7 +6,7 @@ import * as hre from 'hardhat'; async function main() { const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; - const zkWallet = new Wallet('0x9d81dd1aaccd4bd613a641e42728ccfa49aaf5c0eda8ce5faeb159c493894329') + const zkWallet = Wallet.fromMnemonic(testMnemonic); const deployer = new Deployer(hre, zkWallet); // deploy proxy From 6743ee622b1f0e960b88cf84d8c94312f84b94b0 Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Mon, 9 Sep 2024 14:30:38 +0200 Subject: [PATCH 20/20] chore: revert a mnemonic --- examples/upgradable-example/scripts/deploy-box-uups.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/upgradable-example/scripts/deploy-box-uups.ts b/examples/upgradable-example/scripts/deploy-box-uups.ts index 53b38e32f..32ac0dde2 100644 --- a/examples/upgradable-example/scripts/deploy-box-uups.ts +++ b/examples/upgradable-example/scripts/deploy-box-uups.ts @@ -9,7 +9,7 @@ async function main() { console.info(chalk.yellow(`Deploying ${contractName}...`)); const testMnemonic = 'stuff slice staff easily soup parent arm payment cotton trade scatter struggle'; - const zkWallet = new Wallet('0x9d81dd1aaccd4bd613a641e42728ccfa49aaf5c0eda8ce5faeb159c493894329') + const zkWallet = Wallet.fromMnemonic(testMnemonic); const deployer = new Deployer(hre, zkWallet);