From 71e11b57baf922f37679a4c1084bcb760dfd1441 Mon Sep 17 00:00:00 2001 From: Mohsen-T Date: Wed, 22 Nov 2023 10:50:45 +0100 Subject: [PATCH 1/5] fix: deployment and upgrades were tested - deployed all contracts on the goerli-testnet - verified all contracts after deployment - upgraded SSVNetworkValidatorsPerOperator and verified again, tested new value - tested to update module by adding SSVOperatorsGetOperator with additional external function --- .openzeppelin/goerli.json | 354 ++++++++++++++++++ .../stage/goerli/modules/SSVOperators.sol | 16 + tasks/deploy.ts | 285 +++++++------- tasks/update-module.ts | 39 +- 4 files changed, 525 insertions(+), 169 deletions(-) create mode 100644 contracts/upgrades/stage/goerli/modules/SSVOperators.sol diff --git a/.openzeppelin/goerli.json b/.openzeppelin/goerli.json index 59b7ac36..63accba1 100644 --- a/.openzeppelin/goerli.json +++ b/.openzeppelin/goerli.json @@ -135,6 +135,16 @@ "address": "0xFe35A31e57946E8aadd25158BdF303A36dEf3332", "txHash": "0x73d4d1df08c7c3d95e8b34545aa55b9ceb7e7e07f7138cb524c7565c56b03e91", "kind": "uups" + }, + { + "address": "0x3983C0E53Efebd957F2e8C788Aaa7Ca8cE35bAc2", + "txHash": "0xddf035a0cf330be5e1bc369680b90dcfa9626e7c2cdceb0d7b6aee9860b37037", + "kind": "uups" + }, + { + "address": "0x909cd19d547aD3C0faa96cD3139C5e579978Cfb3", + "txHash": "0x7f31d08c37324795c4b92870ebc4765958490818aa138b3761ad94449a1f771c", + "kind": "uups" } ], "impls": { @@ -7345,6 +7355,350 @@ } } } + }, + "c319dae004e883cdd24ab7834715e77958c6beccd0f2cea7e46e804b8f89f295": { + "address": "0x5960ba5BC8956B47e88164C35Ef556c75312eF76", + "txHash": "0x9169d7203995d13ec49119d49a1d32fb9e5f5be8532d536f26188f14a33251c2", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_pendingOwner", + "offset": 0, + "slot": "201", + "type": "t_address", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "8a3382629da06790720d2d37ed76d51b1f949d6c3b17919f08f3b6842b9de108": { + "address": "0x352A82Fb26063c603a055101255471fc0B923224", + "txHash": "0x7cc2057018d99b95e52d4c2e9593017b38eb5e61d67b376a1b1c8c45cae1f51f", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_pendingOwner", + "offset": 0, + "slot": "201", + "type": "t_address", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" + }, + { + "label": "ssvNetwork", + "offset": 0, + "slot": "251", + "type": "t_contract(ISSVViews)4293", + "contract": "SSVNetworkViews", + "src": "contracts/SSVNetworkViews.sol:19" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)50_storage", + "contract": "SSVNetworkViews", + "src": "contracts/SSVNetworkViews.sol:23" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(ISSVViews)4293": { + "label": "contract ISSVViews", + "numberOfBytes": "20" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "6ee7e1de552b998c7b4106a6c1699e2e0876dcb8f5d97a26171791ea4d6ac1ff": { + "address": "0x9Ee003976df2B7F7b7BDd7E9dd38570A306B415F", + "txHash": "0x7386e2307ad22733e085e2583125c48139087106493d9b0c0357ce3452770a6b", + "layout": { + "solcVersion": "0.8.18", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_pendingOwner", + "offset": 0, + "slot": "201", + "type": "t_address", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "Ownable2StepUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/contracts/upgrades/stage/goerli/modules/SSVOperators.sol b/contracts/upgrades/stage/goerli/modules/SSVOperators.sol new file mode 100644 index 00000000..650b8405 --- /dev/null +++ b/contracts/upgrades/stage/goerli/modules/SSVOperators.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.18; + +import "../../../../modules/SSVOperators.sol"; + +contract SSVOperatorsGetOperator is SSVOperators { + /****************************************/ + /* Upgraded Operator External Functions */ + /****************************************/ + + function getOperator(uint64 operatorId) external view returns(Operator memory) { + StorageData storage s = SSVStorage.load(); + Operator memory operator = s.operators[operatorId]; + return operator; + } +} diff --git a/tasks/deploy.ts b/tasks/deploy.ts index 8a3ad9b0..5e931e31 100644 --- a/tasks/deploy.ts +++ b/tasks/deploy.ts @@ -1,5 +1,5 @@ -import { task, subtask, types } from "hardhat/config"; -import { SSVModules } from "./config"; +import { task, subtask, types } from 'hardhat/config'; +import { SSVModules } from './config'; /** @title Hardhat task to deploy all required contracts for SSVNetwork. @@ -15,32 +15,28 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. This task assumes that the SSVModules enum and deployment tasks for individual contracts have been properly defined. */ -task("deploy:all", "Deploy SSVNetwork, SSVNetworkViews and module contracts") - .setAction(async ({ }, hre) => { - const [deployer] = await ethers.getSigners(); - console.log(`Deploying contracts with the account:${deployer.address}`); - - const ssvTokenAddress = await hre.run("deploy:mock-token"); - const operatorsModAddress = await hre.run("deploy:module", { module: SSVModules[SSVModules.SSVOperators] }); - const clustersModAddress = await hre.run("deploy:module", { module: SSVModules[SSVModules.SSVClusters] }); - const daoModAddress = await hre.run("deploy:module", { module: SSVModules[SSVModules.SSVDAO] }); - const viewsModAddress = await hre.run("deploy:module", { module: SSVModules[SSVModules.SSVViews] }); - - const { ssvNetworkProxyAddress: ssvNetworkAddress } = await hre.run("deploy:ssv-network", - { - operatorsModAddress, - clustersModAddress, - daoModAddress, - viewsModAddress, - ssvTokenAddress - }); - - await hre.run("deploy:ssv-network-views", - { - ssvNetworkAddress - }); - }); - +task('deploy:all', 'Deploy SSVNetwork, SSVNetworkViews and module contracts').setAction(async ({}, hre) => { + const [deployer] = await ethers.getSigners(); + console.log(`Deploying contracts with the account:${deployer.address}`); + + const ssvTokenAddress = await hre.run('deploy:mock-token'); + const operatorsModAddress = await hre.run('deploy:module', { module: SSVModules[SSVModules.SSVOperators] }); + const clustersModAddress = await hre.run('deploy:module', { module: SSVModules[SSVModules.SSVClusters] }); + const daoModAddress = await hre.run('deploy:module', { module: SSVModules[SSVModules.SSVDAO] }); + const viewsModAddress = await hre.run('deploy:module', { module: SSVModules[SSVModules.SSVViews] }); + + const { ssvNetworkProxyAddress: ssvNetworkAddress } = await hre.run('deploy:ssv-network', { + operatorsModAddress, + clustersModAddress, + daoModAddress, + viewsModAddress, + ssvTokenAddress, + }); + + await hre.run('deploy:ssv-network-views', { + ssvNetworkAddress, + }); +}); /** @title Hardhat task to deploy a main implementation contract for SSVNetwork or SSVNetworkViews. @@ -56,13 +52,11 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. This task uses the "deploy:impl" subtask for the actual deployment. */ -task("deploy:main-impl", "Deploys SSVNetwork / SSVNetworkViews implementation contract") - .addParam("contract", "New contract implemetation", null, types.string) - .setAction(async ({ contract }, hre) => { - - await hre.run("deploy:impl", { contract }); - }); - +task('deploy:main-impl', 'Deploys SSVNetwork / SSVNetworkViews implementation contract') + .addParam('contract', 'New contract implemetation', null, types.string) + .setAction(async ({ contract }, hre) => { + await hre.run('deploy:impl', { contract }); + }); /** @title Hardhat subtask to deploy an SSV module contract. @@ -76,48 +70,47 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. This subtask uses the "deploy:impl" subtask for the actual deployment. */ -subtask("deploy:module", "Deploys a new module contract") - .addParam("module", "SSV Module", null, types.string) - .setAction(async ({ module }, hre) => { - const moduleValues = Object.values(SSVModules); - if (!moduleValues.includes(module)) { - throw new Error(`Invalid SSVModule: ${module}. Expected one of: ${moduleValues.join(", ")}`); - } - - const moduleAddress = await hre.run("deploy:impl", { contract: module }); - return moduleAddress; - }); - -task("deploy:token", "Deploys SSV Token") - .setAction(async ({ }, hre) => { - console.log('Deploying SSV Network Token'); - - const ssvTokenFactory = await ethers.getContractFactory('SSVToken'); - const ssvToken = await ssvTokenFactory.deploy(); - await ssvToken.deployed(); - - console.log(`SSV Network Token deployed to: ${ssvToken.address}`); - - }); +subtask('deploy:module', 'Deploys a new module contract') + .addParam('module', 'SSV Module', null, types.string) + .addParam('contract', 'SSV Module Contract', null, types.string) + .setAction(async ({ module, contract }, hre) => { + const moduleValues = Object.values(SSVModules); + if (!moduleValues.includes(module)) { + throw new Error(`Invalid SSVModule: ${module}. Expected one of: ${moduleValues.join(', ')}`); + } + + if (contract === undefined) contract = module; + const moduleAddress = await hre.run('deploy:impl', { contract }); + return moduleAddress; + }); + +task('deploy:token', 'Deploys SSV Token').setAction(async ({}, hre) => { + console.log('Deploying SSV Network Token'); + + const ssvTokenFactory = await ethers.getContractFactory('SSVToken'); + const ssvToken = await ssvTokenFactory.deploy(); + await ssvToken.deployed(); + + console.log(`SSV Network Token deployed to: ${ssvToken.address}`); +}); /** -* @title Hardhat subtask to deploy or fetch an SSV Token contract. -* The ssvToken parameter in the hardhat's network section, specifies the address of the SSV Token contract. -* If not provided, it will deploy a new MockToken contract. -* @returns {string} The address of the deployed or fetched SSV Token contract. -*/ -subtask("deploy:mock-token", "Deploys / fetch SSV Token") - .setAction(async ({ }, hre) => { - const tokenAddress = hre.network.config.ssvToken; - if (tokenAddress) return tokenAddress; - - // Local networks, deploy mock token - const ssvTokenFactory = await ethers.getContractFactory('SSVTokenMock'); - const ssvToken = await ssvTokenFactory.deploy(); - await ssvToken.deployed(); - - return ssvToken.address; - }); + * @title Hardhat subtask to deploy or fetch an SSV Token contract. + * The ssvToken parameter in the hardhat's network section, specifies the address of the SSV Token contract. + * If not provided, it will deploy a new MockToken contract. + * @returns {string} The address of the deployed or fetched SSV Token contract. + */ +subtask('deploy:mock-token', 'Deploys / fetch SSV Token').setAction(async ({}, hre) => { + const tokenAddress = hre.network.config.ssvToken; + if (tokenAddress) return tokenAddress; + + // Local networks, deploy mock token + const ssvTokenFactory = await ethers.getContractFactory('SSVTokenMock'); + const ssvToken = await ssvTokenFactory.deploy(); + await ssvToken.deployed(); + + return ssvToken.address; +}); /** @title Hardhat subtask to deploy a new implementation contract. @@ -130,19 +123,19 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. The contract specified should be already compiled and exist in the 'artifacts' directory. */ -subtask("deploy:impl", "Deploys an implementation contract") - .addParam("contract", "New contract implemetation", null, types.string) - .setAction(async ({ contract }) => { - // Initialize contract - const contractFactory = await ethers.getContractFactory(contract); - - // Deploy implemetation contract - const contractImpl = await contractFactory.deploy(); - await contractImpl.deployed(); - console.log(`${contract} implementation deployed to: ${contractImpl.address}`); - - return contractImpl.address; - }); +subtask('deploy:impl', 'Deploys an implementation contract') + .addParam('contract', 'New contract implemetation', null, types.string) + .setAction(async ({ contract }) => { + // Initialize contract + const contractFactory = await ethers.getContractFactory(contract); + + // Deploy implemetation contract + const contractImpl = await contractFactory.deploy(); + await contractImpl.deployed(); + console.log(`${contract} implementation deployed to: ${contractImpl.address}`); + + return contractImpl.address; + }); /** @title Hardhat subtask to deploy the SSVNetwork contract. @@ -161,50 +154,46 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. The 'SSVNetwork' contract specified should be already compiled and exist in the 'artifacts' directory. */ -subtask("deploy:ssv-network", "Deploys SSVNetwork contract") - .addPositionalParam("operatorsModAddress", "Operators module address", null, types.string) - .addPositionalParam("clustersModAddress", "Clusters module address", null, types.string) - .addPositionalParam("daoModAddress", "DAO module address", null, types.string) - .addPositionalParam("viewsModAddress", "Views module address", null, types.string) - .addPositionalParam("ssvTokenAddress", "SSV Token address", null, types.string) - .setAction(async ({ +subtask('deploy:ssv-network', 'Deploys SSVNetwork contract') + .addPositionalParam('operatorsModAddress', 'Operators module address', null, types.string) + .addPositionalParam('clustersModAddress', 'Clusters module address', null, types.string) + .addPositionalParam('daoModAddress', 'DAO module address', null, types.string) + .addPositionalParam('viewsModAddress', 'Views module address', null, types.string) + .addPositionalParam('ssvTokenAddress', 'SSV Token address', null, types.string) + .setAction(async ({ operatorsModAddress, clustersModAddress, daoModAddress, viewsModAddress, ssvTokenAddress }) => { + const ssvNetworkFactory = await ethers.getContractFactory('SSVNetwork'); + + // deploy SSVNetwork + console.log(`Deploying SSVNetwork with ssvToken ${ssvTokenAddress}`); + const ssvNetwork = await upgrades.deployProxy( + ssvNetworkFactory, + [ + ssvTokenAddress, operatorsModAddress, clustersModAddress, daoModAddress, viewsModAddress, - ssvTokenAddress }) => { - - - const ssvNetworkFactory = await ethers.getContractFactory('SSVNetwork'); - - // deploy SSVNetwork - console.log(`Deploying SSVNetwork with ssvToken ${ssvTokenAddress}`); - const ssvNetwork = await upgrades.deployProxy(ssvNetworkFactory, [ - ssvTokenAddress, - operatorsModAddress, - clustersModAddress, - daoModAddress, - viewsModAddress, - process.env.MINIMUM_BLOCKS_BEFORE_LIQUIDATION, - process.env.MINIMUM_LIQUIDATION_COLLATERAL, - process.env.VALIDATORS_PER_OPERATOR_LIMIT, - process.env.DECLARE_OPERATOR_FEE_PERIOD, - process.env.EXECUTE_OPERATOR_FEE_PERIOD, - process.env.OPERATOR_MAX_FEE_INCREASE - ], - { - kind: "uups" - }); - await ssvNetwork.deployed(); - - const ssvNetworkProxyAddress = ssvNetwork.address; - const ssvNetworkImplAddress = await upgrades.erc1967.getImplementationAddress(ssvNetwork.address); - - console.log(`SSVNetwork proxy deployed to: ${ssvNetworkProxyAddress}`); - console.log(`SSVNetwork implementation deployed to: ${ssvNetworkImplAddress}`); - - return { ssvNetworkProxyAddress, ssvNetworkImplAddress }; - }); + process.env.MINIMUM_BLOCKS_BEFORE_LIQUIDATION, + process.env.MINIMUM_LIQUIDATION_COLLATERAL, + process.env.VALIDATORS_PER_OPERATOR_LIMIT, + process.env.DECLARE_OPERATOR_FEE_PERIOD, + process.env.EXECUTE_OPERATOR_FEE_PERIOD, + process.env.OPERATOR_MAX_FEE_INCREASE, + ], + { + kind: 'uups', + }, + ); + await ssvNetwork.deployed(); + + const ssvNetworkProxyAddress = ssvNetwork.address; + const ssvNetworkImplAddress = await upgrades.erc1967.getImplementationAddress(ssvNetwork.address); + + console.log(`SSVNetwork proxy deployed to: ${ssvNetworkProxyAddress}`); + console.log(`SSVNetwork implementation deployed to: ${ssvNetworkImplAddress}`); + + return { ssvNetworkProxyAddress, ssvNetworkImplAddress }; + }); /** @title Hardhat subtask to deploy the SSVNetworkViews contract. @@ -217,26 +206,22 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. The 'SSVNetworkViews' contract specified should be already compiled and exist in the 'artifacts' directory. */ -subtask("deploy:ssv-network-views", "Deploys SSVNetworkViews contract") - .addParam("ssvNetworkAddress", "SSVNetwork address", null, types.string) - .setAction(async ({ - ssvNetworkAddress }) => { - const ssvNetworkViewsFactory = await ethers.getContractFactory('SSVNetworkViews'); - - // deploy SSVNetwork - const ssvNetworkViews = await upgrades.deployProxy(ssvNetworkViewsFactory, [ - ssvNetworkAddress - ], - { - kind: "uups" - }); - await ssvNetworkViews.deployed(); - - const ssvNetworkViewsProxyAddress = ssvNetworkViews.address; - const ssvNetworkViewsImplAddress = await upgrades.erc1967.getImplementationAddress(ssvNetworkViews.address); - - console.log(`SSVNetworkViews proxy deployed to: ${ssvNetworkViewsProxyAddress}`); - console.log(`SSVNetworkViews implementation deployed to: ${ssvNetworkViewsImplAddress}`); - - return { ssvNetworkViewsProxyAddress, ssvNetworkViewsImplAddress }; +subtask('deploy:ssv-network-views', 'Deploys SSVNetworkViews contract') + .addParam('ssvNetworkAddress', 'SSVNetwork address', null, types.string) + .setAction(async ({ ssvNetworkAddress }) => { + const ssvNetworkViewsFactory = await ethers.getContractFactory('SSVNetworkViews'); + + // deploy SSVNetwork + const ssvNetworkViews = await upgrades.deployProxy(ssvNetworkViewsFactory, [ssvNetworkAddress], { + kind: 'uups', }); + await ssvNetworkViews.deployed(); + + const ssvNetworkViewsProxyAddress = ssvNetworkViews.address; + const ssvNetworkViewsImplAddress = await upgrades.erc1967.getImplementationAddress(ssvNetworkViews.address); + + console.log(`SSVNetworkViews proxy deployed to: ${ssvNetworkViewsProxyAddress}`); + console.log(`SSVNetworkViews implementation deployed to: ${ssvNetworkViewsImplAddress}`); + + return { ssvNetworkViewsProxyAddress, ssvNetworkViewsImplAddress }; + }); diff --git a/tasks/update-module.ts b/tasks/update-module.ts index f2221357..7db69bdc 100644 --- a/tasks/update-module.ts +++ b/tasks/update-module.ts @@ -1,5 +1,5 @@ -import { task, types } from "hardhat/config"; -import { SSVModules } from "./config"; +import { task, types } from 'hardhat/config'; +import { SSVModules } from './config'; /** @title Hardhat task to update a module contract in the SSVNetwork. @@ -17,24 +17,25 @@ The deployer account used will be the first one returned by ethers.getSigners(). Therefore, it should be appropriately configured in your Hardhat network configuration. The module's contract specified should be already compiled and exist in the 'artifacts' directory. */ -task("update:module", "Deploys a new module contract and links it to SSVNetwork") - .addParam("module", "SSV Module", null, types.string) - .addOptionalParam("attachModule", "Attach module to SSVNetwork contract", false, types.boolean) - .addOptionalParam("proxyAddress", "Proxy address of SSVNetwork / SSVNetworkViews", '', types.string) - .setAction(async ({ module, attachModule, proxyAddress }, hre) => { - if (attachModule && !proxyAddress) throw new Error("SSVNetwork proxy address not set."); +task('update:module', 'Deploys a new module contract and links it to SSVNetwork') + .addParam('module', 'SSV Module', null, types.string) + .addParam('contract', 'SSV Module Contract', null, types.string) + .addOptionalParam('attachModule', 'Attach module to SSVNetwork contract', false, types.boolean) + .addOptionalParam('proxyAddress', 'Proxy address of SSVNetwork / SSVNetworkViews', '', types.string) + .setAction(async ({ module, contract, attachModule, proxyAddress }, hre) => { + if (attachModule && !proxyAddress) throw new Error('SSVNetwork proxy address not set.'); - const [deployer] = await ethers.getSigners(); - console.log(`Deploying contracts with the account: ${deployer.address}`); - const moduleAddress = await hre.run("deploy:module", { module }); + const [deployer] = await ethers.getSigners(); + console.log(`Deploying contracts with the account: ${deployer.address}`); + const moduleAddress = await hre.run('deploy:module', { module, contract }); - if (attachModule) { - if (!proxyAddress) throw new Error("SSVNetwork proxy address not set."); + if (attachModule) { + if (!proxyAddress) throw new Error('SSVNetwork proxy address not set.'); - const ssvNetworkFactory = await ethers.getContractFactory('SSVNetwork'); - const ssvNetwork = await ssvNetworkFactory.attach(proxyAddress); + const ssvNetworkFactory = await ethers.getContractFactory('SSVNetwork'); + const ssvNetwork = await ssvNetworkFactory.attach(proxyAddress); - await ssvNetwork.updateModule(SSVModules[module], moduleAddress); - console.log(`${module} module attached to SSVNetwork succesfully`); - } - }); \ No newline at end of file + await ssvNetwork.updateModule(SSVModules[module], moduleAddress); + console.log(`${module} module attached to SSVNetwork succesfully`); + } + }); From 88d22b1152835f19384c4f5de6681d30c6836eda Mon Sep 17 00:00:00 2001 From: Mohsen-T Date: Wed, 22 Nov 2023 17:07:36 +0100 Subject: [PATCH 2/5] fix: changed contract name --- .../stage/goerli/modules/SSVOperators.sol | 16 -------------- .../stage/goerli/modules/SSVOperatorsV2.sol | 22 +++++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) delete mode 100644 contracts/upgrades/stage/goerli/modules/SSVOperators.sol create mode 100644 contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol diff --git a/contracts/upgrades/stage/goerli/modules/SSVOperators.sol b/contracts/upgrades/stage/goerli/modules/SSVOperators.sol deleted file mode 100644 index 650b8405..00000000 --- a/contracts/upgrades/stage/goerli/modules/SSVOperators.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.18; - -import "../../../../modules/SSVOperators.sol"; - -contract SSVOperatorsGetOperator is SSVOperators { - /****************************************/ - /* Upgraded Operator External Functions */ - /****************************************/ - - function getOperator(uint64 operatorId) external view returns(Operator memory) { - StorageData storage s = SSVStorage.load(); - Operator memory operator = s.operators[operatorId]; - return operator; - } -} diff --git a/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol b/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol new file mode 100644 index 00000000..eaa53a0d --- /dev/null +++ b/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.18; + +import "../../../../modules/SSVOperators.sol"; +import "../../../../libraries/Types.sol"; + +contract SSVOperatorsV2 is SSVOperators { + using Types64 for uint64; + /****************************************/ + /* Upgraded Operator External Functions */ + /****************************************/ + + function getOperatorById(uint64 operatorId) external view returns (address, uint256, uint32, address, bool, bool) { + StorageData storage s = SSVStorage.load(); + Operator memory operator = s.operators[operatorId]; + address whitelisted = s.operatorsWhitelist[operatorId]; + bool isPrivate = whitelisted == address(0) ? false : true; + bool isActive = operator.snapshot.block == 0 ? false : true; + + return (operator.owner, operator.fee.expand(), operator.validatorCount, whitelisted, isPrivate, isActive); + } +} From 79cc73777f413365339182cd109db124d545b724 Mon Sep 17 00:00:00 2001 From: Mohsen-T Date: Wed, 22 Nov 2023 18:14:29 +0100 Subject: [PATCH 3/5] fix: updated documentations --- README.md | 2 +- docs/local-dev.md | 48 ++++++++++++++++++++++++++++++++++++------ docs/tasks.md | 36 +++++++++++++++++++++++-------- tasks/update-module.ts | 1 + 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5cd2d984..ecc9cce3 100644 --- a/README.md +++ b/README.md @@ -39,4 +39,4 @@ If you believe you've identified a vulnerability in our smart contracts, we enco Visit our [bounty page](https://immunefi.com/bounty/ssvnetwork/) to get detailed information on the types of vulnerabilities we're interested in, potential reward amounts, and the guidelines for participation. -Please note: Failing to abide by the participation guidelines may result in disqualification from the program and forfeiture of potential rewards. \ No newline at end of file +Please note: Failing to abide by the participation guidelines may result in disqualification from the program and forfeiture of potential rewards. diff --git a/docs/local-dev.md b/docs/local-dev.md index d159e826..2d909082 100644 --- a/docs/local-dev.md +++ b/docs/local-dev.md @@ -1,15 +1,19 @@ # SSV Network -### [Intro](../README.md) | [Architecture](architecture.md) | [Setup](setup.md) | [Tasks](tasks.md) | Local development | [Roles](roles.md) +### [Intro](../README.md) | [Architecture](architecture.md) | [Setup](setup.md) | [Tasks](tasks.md) | Local development | [Roles](roles.md) ## Running against a local node / testnet + You can deploy and run these contracts in a local node like Hardhat's, Ganache, or public testnets. This guide will cover the process. ### Run [Setup](setup.md) + Execute the steps to set up all tools needed. ### Configure Environment + Copy [.env.example](../.env.example) to `.env` and edit to suit. + - `[NETWORK]_ETH_NODE_URL` RPC URL of the node - `[NETWORK]_OWNER_PRIVATE_KEY` Private key of the deployer account, without 0x prefix - `GAS_PRICE` Example 30000000000 @@ -17,39 +21,46 @@ Copy [.env.example](../.env.example) to `.env` and edit to suit. - `ETHERSCAN_KEY` Etherescan API key to verify deployed contracts - `SSV_TOKEN_ADDRESS` SSV Token contract address to be used in custom networks. Keep it empty to deploy a mocked SSV token. - `MINIMUM_BLOCKS_BEFORE_LIQUIDATION` A number of blocks before the cluster enters into a liquidatable state. Example: 214800 = 30 days -- `OPERATOR_MAX_FEE_INCREASE` The fee increase limit in percentage with this format: 100% = 10000, 10% = 1000 - using 10000 to represent 2 digit precision +- `OPERATOR_MAX_FEE_INCREASE` The fee increase limit in percentage with this format: 100% = 10000, 10% = 1000 - using 10000 to represent 2 digit precision - `DECLARE_OPERATOR_FEE_PERIOD` The period in which an operator can declare a fee change (seconds) - `EXECUTE_OPERATOR_FEE_PERIOD` The period in which an operator fee change can be executed (seconds) - `VALIDATORS_PER_OPERATOR_LIMIT` The number of validators an operator can manage - `MINIMUM_LIQUIDATION_COLLATERAL` The lowest number in wei a cluster can have before its liquidatable - #### Network configuration + In [hardhat.config.ts](../hardhat.config.ts) you can find specific configs for different networks, that are taken into account only when the `[NETWORK]_ETH_NODE_URL` parameter in `.env` file is set. For example, in `.env` file you can set: + ``` GOERLI_ETH_NODE_URL="https://goerli.infura.io/v3/..." GOERLI_OWNER_PRIVATE_KEY="d79d.." ``` + That means Hardhat will pick `config.networks.goerli` section in `hardhat.config.ts` to set the network parameters. ### Start the local node + To run the local node, execute the command in a separate terminal. ```sh npx hardhat node ``` + For more details about it and how to use MainNet forking you can find [here](https://hardhat.org/hardhat-network/). ### Deployment + The inital deployment process involves the deployment of all main modules (SSVClusters, SSVOperators, SSVDAO and SSVViews), SSVNetwork and SSVNetworkViews contracts. Note: The SSV token address used when deploying to live networks (goerli, mainnet) is set in the hardhat config file. To deploy the contracts to a custom network defined in the hardhat config file, leave `SSVTOKEN_ADDRESS` empty in the `.env` file. You can set a specific SSV token address for custom networks too, if needed. To run the deployment, execute: + ```sh npx hardhat --network deploy:all ``` + Output of this action will be: ```sh @@ -65,10 +76,13 @@ Deploying SSVNetworkViews with SSVNetwork 0x5FC8... SSVNetworkViews proxy deployed to: 0xa513... SSVNetworkViews implementation deployed to: 0x0165... ``` -As general rule, you can target any network configured in the `hardhat.config.ts`, specifying the right [network]_ETH_NODE_URL and [network]_OWNER_PRIVATE_KEY in `.env` file. + +As general rule, you can target any network configured in the `hardhat.config.ts`, specifying the right [network]\_ETH_NODE_URL and [network]\_OWNER_PRIVATE_KEY in `.env` file. ### Verification on etherscan (only public networks) + You can now go to Etherscan and see: + - `SSVNetwork` proxy contract is deployed to the address shown previously in `SSVNetwork proxy deployed to` - `SSVNetwork` implementation contract is deployed to the address shown previously in `SSVNetwork implementation deployed to` - `SSVNetworkViews` proxy contract is deployed to the address shown previously in `SSVNetworkViews proxy deployed to` @@ -78,15 +92,26 @@ Open `.openzeppelin/.json` file and find `[impls..address]` value You will find 2 `[impls.]` entries, one for `SSVNetwork` and another for `SSVNetworkViews`. Run this verification process for both. -You can take it from the output of the `deploy-all.ts` script. +You can take it from the output of the `npx hardhat --network deploy:all` command. + +To verify a proxy contract (SSVNetwork, SSVNetworkViews), run this: + +```sh +npx hardhat verify --network +``` + +By verifying a contract using its proxy address, the verification process for both the proxy and the implementation contracts is conducted seamlessly. +The proxy contract is automatically linked to the implementation contract. +As a result, users will be able to view interfaces of both the proxy and the implementation contracts on the Etherscan website's contract page, ensuring comprehensive visibility and transparency. -To verify an implementation contract (SSVNetwork, SSVNetworkViews or any module), run this: +To verify a module contract (SSVClusters, SSVOperators, SSVDAO, SSVViews), run this: ```sh npx hardhat verify --network ``` Output of this action will be: + ```sh Nothing to compile No need to generate any newer typings. @@ -99,3 +124,14 @@ https://goerli.etherscan.io/address/0x227...#code ``` After this action, you can go to the proxy contract in Etherscan and start interacting with it. + +### How to resolve issues during the verification + +- Error: no such file ro directory, open ‘…/artifacts/build-info/XXXX...XXXX.json’ + +This issue can be resolved by executing the following commands. + +```sh +npx hardhat clean +npx hardhat compile +``` diff --git a/docs/tasks.md b/docs/tasks.md index 240817a4..5370c160 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -3,9 +3,11 @@ ### [Intro](../README.md) | [Architecture](architecture.md) | [Setup](setup.md) | Tasks | [Local development](local-dev.md) | [Roles](roles.md) ## Development scripts + All scripts can be executed using `package.json` scripts. - ### Build the contracts +### Build the contracts + This creates the build artifacts for deployment or testing ``` @@ -13,6 +15,7 @@ npm run build ``` ### Test the contracts + This builds the contracts and runs the unit tests. It also runs the gas reporter and it outputs the report at the end of the tests. ``` @@ -20,6 +23,7 @@ npm run test ``` ### Run the code coverage + This builds the contracts and runs the code coverage. This is slower than testing since it makes sure that every line of our contracts is tested. It outputs the report in folder `coverage`. ``` @@ -27,27 +31,34 @@ npm run solidity-coverage ``` ### Slither + Runs the static analyzer [Slither](https://github.com/crytic/slither), to search for common solidity vulnerabilities. By default it analyzes all contracts. -```npm run slither``` +`npm run slither` ### Size contracts + Compiles the contracts and report the size of each one. Useful to check to not surpass the 24k limit. + ``` npm run size-contracts ``` ## Development tasks + This project uses hardhat tasks to perform the deployment and upgrade of the main contracts and modules. Following Hardhat's way of working, you must specify the network against which you want to run the task using the `--network` parameter. In all the following examples, the goerli network will be used, but you can specify any defined in your `hardhat.config` file. ### Deploy all contracts + Runs the deployment of the main SSVNetwork and SSVNetworkViews contracts, along with their associated modules: + ``` npx hardhat --network goerli_testnet deploy:all ``` When deploying to live networks like Goerli or Mainnet, please double check the environment variables: + - MINIMUM_BLOCKS_BEFORE_LIQUIDATION - MINIMUM_LIQUIDATION_COLLATERAL - VALIDATORS_PER_OPERATOR_LIMIT @@ -56,12 +67,15 @@ When deploying to live networks like Goerli or Mainnet, please double check the - OPERATOR_MAX_FEE_INCREASE ## Upgrade process + We use [UUPS Proxy Upgrade pattern](https://docs.openzeppelin.com/contracts/4.x/api/proxy) for `SSVNetwork` and `SSVNetworkViews` contracts to have an ability to upgrade them later. **Important**: It's critical to not add any state variable to `SSVNetwork` nor `SSVNetworkViews` when upgrading. All the state variables are managed by [SSVStorage](../contracts/libraries/SSVStorage.sol) and [SSVStorageProtocol](../contracts/libraries/SSVStorageProtocol.sol). Only modify the logic part of the main contracts or the modules. ### Upgrade SSVNetwork / SSVNetworkViews + #### Upgrade contract logic + In this case, the upgrade add / delete / modify a function, but no other piece in the system is changed (libraries or modules). Set `SSVNETWORK_PROXY_ADDRESS` in `.env` file to the right value. @@ -73,18 +87,22 @@ Usage: hardhat [GLOBAL OPTIONS] upgrade:proxy [--contract ] [--init-func OPTIONS: --contract New contract upgrade - --init-function Function to be executed after upgrading + --init-function Function to be executed after upgrading --proxy-address Proxy address of SSVNetwork / SSVNetworkViews POSITIONAL ARGUMENTS: - params Function parameters + params Function parameters Example: npx hardhat --network goerli_testnet upgrade:proxy --proxy-address 0x1234... --contract SSVNetworkV2 --init-function initializev2 param1 param2 ``` +It is crucial to verify the upgraded contract using its proxy address. +This ensures that users can interact with the correct, upgraded implementation on Etherscan. + ### Update a module -Sometimes you only need to perform changes in the logic of a function of a module, add a private function or do something that doesn't affect other components in the architecture. Then you can use the task to update a module. + +Sometimes you only need to perform changes in the logic of a function of a module, add a private function or do something that doesn't affect other components in the architecture. Then you can use the task to update a module. This task first deploys a new version of a specified SSV module contract, and then updates the SSVNetwork contract to use this new module version only if `--attach-module` flag is set to `true`. @@ -95,25 +113,27 @@ OPTIONS: --attach-module Attach module to SSVNetwork contract (default: false) --module SSV Module + --contract SSV Module Contract to be used for updating --proxy-address Proxy address of SSVNetwork / SSVNetworkViews (default: null) Example: Update 'SSVOperators' module contract in the SSVNetwork -npx hardhat --network goerli_testnet update:module --module SSVOperators --attach-module true --proxy-address 0x1234... +npx hardhat --network goerli_testnet update:module --module SSVOperators --contract SSVOperatorsV2 --attach-module true --proxy-address 0x1234... ``` ### Upgrade a library + When you change a library that `SSVNetwork` uses, you need to also update all modules where that library is used. Set `SSVNETWORK_PROXY_ADDRESS` in `.env` file to the right value. Run the task to upgrade SSVNetwork proxy contract as described in [Upgrade SSVNetwork / SSVNetworkViews](#upgrade-contract-logic) - Run the right script to update the module affected by the library change, as described in [Update a module](#update-a-module) section. ### Manual upgrade of SSVNetwork / SSVNetworkViews + Validates and deploys a new implementation contract. Use this task to prepare an upgrade to be run from an owner address you do not control directly or cannot use from Hardhat. ``` @@ -129,5 +149,3 @@ npx hardhat --network goerli_testnet upgrade:prepare --proxy-address 0x1234... - ``` The task will return the new implementation address. After that, you can run `upgradeTo` or `upgradeToAndCall` in SSVNetwork / SSVNetworkViews proxy address, providing it as a parameter. - - diff --git a/tasks/update-module.ts b/tasks/update-module.ts index 7db69bdc..01d78b2b 100644 --- a/tasks/update-module.ts +++ b/tasks/update-module.ts @@ -7,6 +7,7 @@ This task first deploys a new version of a specified SSV module contract, and th The module's name is required and it's expected to match one of the SSVModules enumeration values. The address of the SSVNetwork Proxy is expected to be set in the environment variable SSVNETWORK_PROXY_ADDRESS. @param {string} module - The name of the SSV module to be updated. +@param {string} contract - The name of the new SSV contract to be used for updating. @param {boolean} attachModule - Flag to attach new deployed module to SSVNetwork contract. Dafaults to true. @param {string} proxyAddress - The proxy address of the SSVNetwork contract. @example From 9b8c2b6bb2765feb6fa9197ea078a9ba61ef672b Mon Sep 17 00:00:00 2001 From: Mohsen-T Date: Tue, 28 Nov 2023 14:11:24 +0100 Subject: [PATCH 4/5] fix: removed SSVOperatorsV2.sol --- .../stage/goerli/modules/SSVOperatorsV2.sol | 22 ------------------- docs/local-dev.md | 2 +- docs/tasks.md | 3 +-- tasks/deploy.ts | 6 ++--- tasks/update-module.ts | 6 ++--- 5 files changed, 6 insertions(+), 33 deletions(-) delete mode 100644 contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol diff --git a/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol b/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol deleted file mode 100644 index eaa53a0d..00000000 --- a/contracts/upgrades/stage/goerli/modules/SSVOperatorsV2.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.18; - -import "../../../../modules/SSVOperators.sol"; -import "../../../../libraries/Types.sol"; - -contract SSVOperatorsV2 is SSVOperators { - using Types64 for uint64; - /****************************************/ - /* Upgraded Operator External Functions */ - /****************************************/ - - function getOperatorById(uint64 operatorId) external view returns (address, uint256, uint32, address, bool, bool) { - StorageData storage s = SSVStorage.load(); - Operator memory operator = s.operators[operatorId]; - address whitelisted = s.operatorsWhitelist[operatorId]; - bool isPrivate = whitelisted == address(0) ? false : true; - bool isActive = operator.snapshot.block == 0 ? false : true; - - return (operator.owner, operator.fee.expand(), operator.validatorCount, whitelisted, isPrivate, isActive); - } -} diff --git a/docs/local-dev.md b/docs/local-dev.md index 2d909082..20f6648a 100644 --- a/docs/local-dev.md +++ b/docs/local-dev.md @@ -127,7 +127,7 @@ After this action, you can go to the proxy contract in Etherscan and start inter ### How to resolve issues during the verification -- Error: no such file ro directory, open ‘…/artifacts/build-info/XXXX...XXXX.json’ +- Error: no such file or directory, open ‘…/artifacts/build-info/XXXX...XXXX.json’ This issue can be resolved by executing the following commands. diff --git a/docs/tasks.md b/docs/tasks.md index 5370c160..edd72489 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -113,13 +113,12 @@ OPTIONS: --attach-module Attach module to SSVNetwork contract (default: false) --module SSV Module - --contract SSV Module Contract to be used for updating --proxy-address Proxy address of SSVNetwork / SSVNetworkViews (default: null) Example: Update 'SSVOperators' module contract in the SSVNetwork -npx hardhat --network goerli_testnet update:module --module SSVOperators --contract SSVOperatorsV2 --attach-module true --proxy-address 0x1234... +npx hardhat --network goerli_testnet update:module --module SSVOperators --attach-module true --proxy-address 0x1234... ``` ### Upgrade a library diff --git a/tasks/deploy.ts b/tasks/deploy.ts index 5e931e31..826cd2a1 100644 --- a/tasks/deploy.ts +++ b/tasks/deploy.ts @@ -72,15 +72,13 @@ This subtask uses the "deploy:impl" subtask for the actual deployment. */ subtask('deploy:module', 'Deploys a new module contract') .addParam('module', 'SSV Module', null, types.string) - .addParam('contract', 'SSV Module Contract', null, types.string) - .setAction(async ({ module, contract }, hre) => { + .setAction(async ({ module }, hre) => { const moduleValues = Object.values(SSVModules); if (!moduleValues.includes(module)) { throw new Error(`Invalid SSVModule: ${module}. Expected one of: ${moduleValues.join(', ')}`); } - if (contract === undefined) contract = module; - const moduleAddress = await hre.run('deploy:impl', { contract }); + const moduleAddress = await hre.run('deploy:impl', { module }); return moduleAddress; }); diff --git a/tasks/update-module.ts b/tasks/update-module.ts index 01d78b2b..e8dbbeef 100644 --- a/tasks/update-module.ts +++ b/tasks/update-module.ts @@ -7,7 +7,6 @@ This task first deploys a new version of a specified SSV module contract, and th The module's name is required and it's expected to match one of the SSVModules enumeration values. The address of the SSVNetwork Proxy is expected to be set in the environment variable SSVNETWORK_PROXY_ADDRESS. @param {string} module - The name of the SSV module to be updated. -@param {string} contract - The name of the new SSV contract to be used for updating. @param {boolean} attachModule - Flag to attach new deployed module to SSVNetwork contract. Dafaults to true. @param {string} proxyAddress - The proxy address of the SSVNetwork contract. @example @@ -20,15 +19,14 @@ The module's contract specified should be already compiled and exist in the 'art */ task('update:module', 'Deploys a new module contract and links it to SSVNetwork') .addParam('module', 'SSV Module', null, types.string) - .addParam('contract', 'SSV Module Contract', null, types.string) .addOptionalParam('attachModule', 'Attach module to SSVNetwork contract', false, types.boolean) .addOptionalParam('proxyAddress', 'Proxy address of SSVNetwork / SSVNetworkViews', '', types.string) - .setAction(async ({ module, contract, attachModule, proxyAddress }, hre) => { + .setAction(async ({ module, attachModule, proxyAddress }, hre) => { if (attachModule && !proxyAddress) throw new Error('SSVNetwork proxy address not set.'); const [deployer] = await ethers.getSigners(); console.log(`Deploying contracts with the account: ${deployer.address}`); - const moduleAddress = await hre.run('deploy:module', { module, contract }); + const moduleAddress = await hre.run('deploy:module', { module }); if (attachModule) { if (!proxyAddress) throw new Error('SSVNetwork proxy address not set.'); From e6d394cead1c3691cb1f81c71a8662a73af3a14c Mon Sep 17 00:00:00 2001 From: Mohsen-T Date: Thu, 30 Nov 2023 11:16:58 +0100 Subject: [PATCH 5/5] fix: updated goerli metadata --- .openzeppelin/goerli.json | 354 -------------------------------------- 1 file changed, 354 deletions(-) diff --git a/.openzeppelin/goerli.json b/.openzeppelin/goerli.json index 63accba1..59b7ac36 100644 --- a/.openzeppelin/goerli.json +++ b/.openzeppelin/goerli.json @@ -135,16 +135,6 @@ "address": "0xFe35A31e57946E8aadd25158BdF303A36dEf3332", "txHash": "0x73d4d1df08c7c3d95e8b34545aa55b9ceb7e7e07f7138cb524c7565c56b03e91", "kind": "uups" - }, - { - "address": "0x3983C0E53Efebd957F2e8C788Aaa7Ca8cE35bAc2", - "txHash": "0xddf035a0cf330be5e1bc369680b90dcfa9626e7c2cdceb0d7b6aee9860b37037", - "kind": "uups" - }, - { - "address": "0x909cd19d547aD3C0faa96cD3139C5e579978Cfb3", - "txHash": "0x7f31d08c37324795c4b92870ebc4765958490818aa138b3761ad94449a1f771c", - "kind": "uups" } ], "impls": { @@ -7355,350 +7345,6 @@ } } } - }, - "c319dae004e883cdd24ab7834715e77958c6beccd0f2cea7e46e804b8f89f295": { - "address": "0x5960ba5BC8956B47e88164C35Ef556c75312eF76", - "txHash": "0x9169d7203995d13ec49119d49a1d32fb9e5f5be8532d536f26188f14a33251c2", - "layout": { - "solcVersion": "0.8.18", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" - }, - { - "label": "__gap", - "offset": 0, - "slot": "51", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" - }, - { - "label": "__gap", - "offset": 0, - "slot": "101", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "151", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pendingOwner", - "offset": 0, - "slot": "201", - "type": "t_address", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)49_storage", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "8a3382629da06790720d2d37ed76d51b1f949d6c3b17919f08f3b6842b9de108": { - "address": "0x352A82Fb26063c603a055101255471fc0B923224", - "txHash": "0x7cc2057018d99b95e52d4c2e9593017b38eb5e61d67b376a1b1c8c45cae1f51f", - "layout": { - "solcVersion": "0.8.18", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" - }, - { - "label": "__gap", - "offset": 0, - "slot": "51", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" - }, - { - "label": "__gap", - "offset": 0, - "slot": "101", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "151", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pendingOwner", - "offset": 0, - "slot": "201", - "type": "t_address", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)49_storage", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" - }, - { - "label": "ssvNetwork", - "offset": 0, - "slot": "251", - "type": "t_contract(ISSVViews)4293", - "contract": "SSVNetworkViews", - "src": "contracts/SSVNetworkViews.sol:19" - }, - { - "label": "__gap", - "offset": 0, - "slot": "252", - "type": "t_array(t_uint256)50_storage", - "contract": "SSVNetworkViews", - "src": "contracts/SSVNetworkViews.sol:23" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(ISSVViews)4293": { - "label": "contract ISSVViews", - "numberOfBytes": "20" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "6ee7e1de552b998c7b4106a6c1699e2e0876dcb8f5d97a26171791ea4d6ac1ff": { - "address": "0x9Ee003976df2B7F7b7BDd7E9dd38570A306B415F", - "txHash": "0x7386e2307ad22733e085e2583125c48139087106493d9b0c0357ce3452770a6b", - "layout": { - "solcVersion": "0.8.18", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:169" - }, - { - "label": "__gap", - "offset": 0, - "slot": "51", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:111" - }, - { - "label": "__gap", - "offset": 0, - "slot": "101", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "151", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pendingOwner", - "offset": 0, - "slot": "201", - "type": "t_address", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:27" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)49_storage", - "contract": "Ownable2StepUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:70" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } } } }