diff --git a/hardhat.config.ts b/hardhat.config.ts index 17f2358f..facbbf00 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,18 +3,37 @@ import "@nomicfoundation/hardhat-toolbox"; import "@openzeppelin/hardhat-upgrades"; import "hardhat-dependency-compiler"; -import {HardhatUserConfig} from "hardhat/config"; +import { HardhatUserConfig } from "hardhat/config"; const DEFAULT_MNEMONIC = "test test test test test test test test test test test junk"; +const INFURA_URL = `https://{network}.infura.io/v3/${process.env.INFURA_PROJECT_ID}`; +const MNEMONIC = process.env.MNEMONIC || DEFAULT_MNEMONIC; +const ACCOUNTS_CONFIG = { + mnemonic: MNEMONIC, + path: "m/44'/60'/0'/0", + initialIndex: 0, + count: 20, +}; + +const COMPILER_SETTINGS = { + optimizer: { + enabled: true, + runs: 999999, + }, +}; -/* - * You need to export an object to set up your config - * Go to https://hardhat.org/config/ to learn more - */ +const COMPILER_VERSIONS = [ + "0.8.17", + "0.8.20", + "0.6.11", + "0.5.12", + "0.5.16" +]; -/** - * @type import('hardhat/config').HardhatUserConfig - */ +const createNetworkConfig = (network: string, providerUrl?: string) => ({ + url: process.env[`${network.toUpperCase()}_PROVIDER`] || providerUrl.replace("{network}", network), + accounts: ACCOUNTS_CONFIG, +}); const config: HardhatUserConfig = { dependencyCompiler: { @@ -22,225 +41,83 @@ const config: HardhatUserConfig = { "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol", "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol", "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol", - ], // , - // keep: true + ], }, solidity: { - compilers: [ - { - version: "0.8.17", - settings: { - optimizer: { - enabled: true, - runs: 999999, - }, - }, - }, - { - version: "0.8.20", - settings: { - optimizer: { - enabled: true, - runs: 999999, - }, - evmVersion: "shanghai", - }, - }, - { - version: "0.6.11", - settings: { - optimizer: { - enabled: true, - runs: 999999, - }, - }, - }, - { - version: "0.5.12", - settings: { - optimizer: { - enabled: true, - runs: 999999, - }, - }, - }, - { - version: "0.5.16", - settings: { - optimizer: { - enabled: true, - runs: 999999, - }, - }, - }, - ], + compilers: COMPILER_VERSIONS.map(version => ({ + version, + settings: COMPILER_SETTINGS, + })), overrides: { "contracts/v2/PolygonRollupManager.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 500, - }, + ...COMPILER_SETTINGS, + runs: 500, evmVersion: "shanghai", - }, // try yul optimizer + }, }, "contracts/v2/PolygonZkEVMBridgeV2.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 999, - }, + ...COMPILER_SETTINGS, + runs: 999, evmVersion: "shanghai", }, }, "contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 500, - }, + ...COMPILER_SETTINGS, + runs: 500, evmVersion: "shanghai", - }, // try yul optimizer + }, }, "contracts/v2/mocks/PolygonRollupManagerMock.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 10, - }, + optimizer: { enabled: true, runs: 10 }, evmVersion: "shanghai", - }, // try yul optimizer + }, }, - // Should have the same optimizations than the RollupManager to verify "contracts/v2/lib/PolygonTransparentProxy.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 500, - }, + ...COMPILER_SETTINGS, + runs: 500, evmVersion: "shanghai", - }, // try yul optimizer + }, }, "contracts/v2/utils/ClaimCompressor.sol": { version: "0.8.20", settings: { - optimizer: { - enabled: true, - runs: 999999, - }, + ...COMPILER_SETTINGS, evmVersion: "shanghai", - //viaIR: true, }, }, }, }, networks: { - mainnet: { - url: process.env.MAINNET_PROVIDER - ? process.env.MAINNET_PROVIDER - : `https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - ropsten: { - url: process.env.ROPSTEN_PROVIDER - ? process.env.ROPSTEN_PROVIDER - : `https://ropsten.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - goerli: { - url: process.env.GOERLI_PROVIDER - ? process.env.GOERLI_PROVIDER - : `https://goerli.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - rinkeby: { - url: process.env.RINKEBY_PROVIDER - ? process.env.RINKEBY_PROVIDER - : `https://rinkeby.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - sepolia: { - url: process.env.SEPOLIA_PROVIDER - ? process.env.SEPOLIA_PROVIDER - : `https://sepolia.infura.io/v3/${process.env.INFURA_PROJECT_ID}`, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, + mainnet: createNetworkConfig('mainnet', INFURA_URL), + ropsten: createNetworkConfig('ropsten', INFURA_URL), + goerli: createNetworkConfig('goerli', INFURA_URL), + rinkeby: createNetworkConfig('rinkeby', INFURA_URL), + sepolia: createNetworkConfig('sepolia', INFURA_URL), localhost: { url: "http://127.0.0.1:8545", - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, + accounts: ACCOUNTS_CONFIG, }, hardhat: { initialDate: "0", allowUnlimitedContractSize: true, initialBaseFeePerGas: 0, - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - polygonZKEVMTestnet: { - url: "https://rpc.cardona.zkevm-rpc.com", - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, - }, - polygonZKEVMMainnet: { - url: "https://zkevm-rpc.com", - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, + accounts: ACCOUNTS_CONFIG, }, + polygonZKEVMTestnet: createNetworkConfig('polygonZKEVMTestnet', "https://rpc.cardona.zkevm-rpc.com"), + polygonZKEVMMainnet: createNetworkConfig('polygonZKEVMMainnet', "https://zkevm-rpc.com"), zkevmDevnet: { url: "http://123:123:123:123:123", - accounts: { - mnemonic: process.env.MNEMONIC || DEFAULT_MNEMONIC, - path: "m/44'/60'/0'/0", - initialIndex: 0, - count: 20, - }, + accounts: ACCOUNTS_CONFIG, }, }, gasReporter: { @@ -250,12 +127,12 @@ const config: HardhatUserConfig = { }, etherscan: { apiKey: { - polygonZKEVMTestnet: `${process.env.ETHERSCAN_ZKEVM_API_KEY}`, - polygonZKEVMMainnet: `${process.env.ETHERSCAN_ZKEVM_API_KEY}`, - goerli: `${process.env.ETHERSCAN_API_KEY}`, - sepolia: `${process.env.ETHERSCAN_API_KEY}`, - mainnet: `${process.env.ETHERSCAN_API_KEY}`, - zkevmDevnet: `${process.env.ETHERSCAN_API_KEY}`, + polygonZKEVMTestnet: process.env.ETHERSCAN_ZKEVM_API_KEY, + polygonZKEVMMainnet: process.env.ETHERSCAN_ZKEVM_API_KEY, + goerli: process.env.ETHERSCAN_API_KEY, + sepolia: process.env.ETHERSCAN_API_KEY, + mainnet: process.env.ETHERSCAN_API_KEY, + zkevmDevnet: process.env.ETHERSCAN_API_KEY, }, customChains: [ { diff --git a/verifyMainnetDeployment/verifyMainnetDeployment.js b/verifyMainnetDeployment/verifyMainnetDeployment.js index 0b7dc7b2..a7ce17fb 100644 --- a/verifyMainnetDeployment/verifyMainnetDeployment.js +++ b/verifyMainnetDeployment/verifyMainnetDeployment.js @@ -7,189 +7,153 @@ const { expect } = require('chai'); const deployMainnet = require("./mainnetDeployment.json"); const mainnetDeployParameters = require("./mainnetDeployParameters.json"); -const pathFflonkVerifier = '../artifacts/contracts/verifiers/FflonkVerifier.sol/FflonkVerifier.json'; -const pathPolygonZkEVMDeployer = '../artifacts/contracts/deployment/PolygonZkEVMDeployer.sol/PolygonZkEVMDeployer.json'; -const pathPolygonZkEVMBridge = '../artifacts/contracts/PolygonZkEVMBridge.sol/PolygonZkEVMBridge.json'; -const pathTransparentProxyOZUpgradeDep = '../node_modules/@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json'; -const pathProxyAdmin = '../artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json'; -const pathTransparentProxy = '../artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json'; -const pathPolygonZkEVMTimelock = '../artifacts/contracts/PolygonZkEVMTimelock.sol/PolygonZkEVMTimelock.json'; -const pathPolygonZkEVM = '../artifacts/contracts/PolygonZkEVM.sol/PolygonZkEVM.json'; -const pathPolygonZkEVMGlobalExitRoot = '../artifacts/contracts/PolygonZkEVMGlobalExitRoot.sol/PolygonZkEVMGlobalExitRoot.json'; - -const FflonkVerifier = require(pathFflonkVerifier); -const PolygonZkEVMDeployer = require(pathPolygonZkEVMDeployer); -const PolygonZkEVMBridge = require(pathPolygonZkEVMBridge); -const TransparentProxyOZUpgradeDep = require(pathTransparentProxyOZUpgradeDep); -const ProxyAdmin = require(pathProxyAdmin); -const TransparentProxy = require(pathTransparentProxy); - - -const etherscanURL = "https://etherscan.io/address/" +const artifactsPath = { + fflonkVerifier: '../artifacts/contracts/verifiers/FflonkVerifier.sol/FflonkVerifier.json', + polygonZkEVMDeployer: '../artifacts/contracts/deployment/PolygonZkEVMDeployer.sol/PolygonZkEVMDeployer.json', + polygonZkEVMBridge: '../artifacts/contracts/PolygonZkEVMBridge.sol/PolygonZkEVMBridge.json', + transparentProxyOZUpgradeDep: '../node_modules/@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json', + proxyAdmin: '../artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json', + transparentProxy: '../artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json', + polygonZkEVMTimelock: '../artifacts/contracts/PolygonZkEVMTimelock.sol/PolygonZkEVMTimelock.json', + polygonZkEVM: '../artifacts/contracts/PolygonZkEVM.sol/PolygonZkEVM.json', + polygonZkEVMGlobalExitRoot: '../artifacts/contracts/PolygonZkEVMGlobalExitRoot.sol/PolygonZkEVMGlobalExitRoot.json' +}; + +// Load contract artifacts +const FflonkVerifier = require(artifactsPath.fflonkVerifier); +const PolygonZkEVMDeployer = require(artifactsPath.polygonZkEVMDeployer); +const PolygonZkEVMBridge = require(artifactsPath.polygonZkEVMBridge); +const TransparentProxyOZUpgradeDep = require(artifactsPath.transparentProxyOZUpgradeDep); +const ProxyAdmin = require(artifactsPath.proxyAdmin); +const TransparentProxy = require(artifactsPath.transparentProxy); + +const etherscanURL = "https://etherscan.io/address/"; + async function main() { - // First verify not immutable conracts - const mainnetProvider = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`); - - // FflonkVerifier - expect(await mainnetProvider.getCode(deployMainnet.fflonkVerifierAddress)) - .to.be.equal(FflonkVerifier.deployedBytecode); - console.log("FflonkVerifier was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.fflonkVerifierAddress) - console.log("Path file: ", path.join(__dirname, pathFflonkVerifier)); - console.log(); - - // PolygonZkEVMDeployer - expect(await mainnetProvider.getCode(deployMainnet.polygonZkEVMDeployerAddress)) - .to.be.equal(PolygonZkEVMDeployer.deployedBytecode); - console.log("PolygonZkEVMDeployer was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.polygonZkEVMDeployerAddress) - console.log("Path file: ", path.join(__dirname, pathPolygonZkEVMDeployer)); - console.log(); - - // Bridge - // Since this contract is a proxy, we will need to verify the implementation - const polygonZkEVMBridgeImpl = await getImplementationAddress(deployMainnet.polygonZkEVMBridgeAddress, mainnetProvider) - - expect(await mainnetProvider.getCode(polygonZkEVMBridgeImpl)) - .to.be.equal(PolygonZkEVMBridge.deployedBytecode); - console.log("PolygonZkEVMBridgeAddress implementation was correctly verified") - console.log("Etherscan URL: ", etherscanURL + polygonZkEVMBridgeImpl) - console.log("Path file: ", path.join(__dirname, pathPolygonZkEVMBridge)); - console.log(); - - // Check transparent Proxys - expect(await mainnetProvider.getCode(deployMainnet.polygonZkEVMBridgeAddress)) - .to.be.equal(TransparentProxy.deployedBytecode); - console.log("PolygonZkEVMBridgeAddress proxy was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.polygonZkEVMBridgeAddress); - console.log("Path file: ", path.join(__dirname, pathTransparentProxy)); - console.log(); - - // The other 3 contracts are immutables, therefore we will deploy them locally and check the btyecode against the deployed one - - // PolygonZkEVMTimelock - const PolygonZkEVMTimelockFactory = await ethers.getContractFactory('PolygonZkEVMTimelock'); - const timelockAddress = mainnetDeployParameters.timelockAddress; //not relevant to deployed bytecode - const minDelayTimelock = mainnetDeployParameters.minDelayTimelock; //not relevant to deployed bytecode - - const PolygonZkEVMTimelock = await PolygonZkEVMTimelockFactory.deploy( - minDelayTimelock, - [timelockAddress], - [timelockAddress], - timelockAddress, - deployMainnet.polygonZkEVMAddress, - ); - PolygonZkEVMTimelock.deployed() - - const deployedBytecodePolygonZkEVMTimelock = await ethers.provider.getCode(PolygonZkEVMTimelock.address); - expect(await mainnetProvider.getCode(deployMainnet.polygonZkEVMTimelockAddress)) - .to.be.equal(deployedBytecodePolygonZkEVMTimelock); - console.log("Timelock was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.polygonZkEVMTimelockAddress); - console.log("Path file: ", path.join(__dirname, pathPolygonZkEVMTimelock)); - console.log(); - - // polygonZkEVMGlobalExitRoot - const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory('PolygonZkEVMGlobalExitRoot'); - const polygonZkEVMGlobalExitRoot = await PolygonZkEVMGlobalExitRootFactory.deploy( - deployMainnet.polygonZkEVMAddress, - deployMainnet.polygonZkEVMBridgeAddress - ); - polygonZkEVMGlobalExitRoot.deployed() - - const deployedBytecodeGlobalExitRoot = await ethers.provider.getCode(polygonZkEVMGlobalExitRoot.address); - const polygonZkEVMGlobalImpl = await getImplementationAddress(deployMainnet.polygonZkEVMGlobalExitRootAddress, mainnetProvider) - - expect(await mainnetProvider.getCode(polygonZkEVMGlobalImpl)) - .to.be.equal(deployedBytecodeGlobalExitRoot); - console.log("PolygonZkEVMGlobalExitRoot implementation was correctly verified") - console.log("Etherscan URL: ", etherscanURL + polygonZkEVMGlobalImpl); - console.log("Path file: ", path.join(__dirname, pathPolygonZkEVMGlobalExitRoot)); - console.log(); - - // Check transparent Proxys - expect(await mainnetProvider.getCode(deployMainnet.polygonZkEVMGlobalExitRootAddress)) - .to.be.equal(TransparentProxyOZUpgradeDep.deployedBytecode); - console.log("PolygonZkEVMGlobalExitRoot proxy was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.polygonZkEVMGlobalExitRootAddress); - console.log("Path file: ", path.join(__dirname, pathTransparentProxyOZUpgradeDep)); - console.log(); - - // PolygonZkEVM - const mainnetChainID = mainnetDeployParameters.chainID; - const mainnetForkID = mainnetDeployParameters.forkID; - const maticAddress = mainnetDeployParameters.maticTokenAddress; - - const PolygonZkEVMFactory = await ethers.getContractFactory('PolygonZkEVM'); - const polygonZkEVMContract = await PolygonZkEVMFactory.deploy( - deployMainnet.polygonZkEVMGlobalExitRootAddress, - maticAddress, - deployMainnet.fflonkVerifierAddress, - deployMainnet.polygonZkEVMBridgeAddress, - mainnetChainID, - mainnetForkID, - ); - polygonZkEVMContract.deployed() - - const deployedBytecodePolygonZkEVM = await ethers.provider.getCode(polygonZkEVMContract.address); - const polygonZkEVMImpl = await getImplementationAddress(deployMainnet.polygonZkEVMAddress, mainnetProvider) - - expect(await mainnetProvider.getCode(polygonZkEVMImpl)) - .to.be.equal(deployedBytecodePolygonZkEVM); - console.log("PolygonZkEVMAddress implementation was correctly verified") - console.log("Etherscan URL: ", etherscanURL + polygonZkEVMImpl); - console.log("Path file: ", path.join(__dirname, pathPolygonZkEVM)); - console.log(); - - // Check transparent Proxys - expect(await mainnetProvider.getCode(deployMainnet.polygonZkEVMAddress)) - .to.be.equal(TransparentProxyOZUpgradeDep.deployedBytecode); - console.log("PolygonZkEVMAddress proxy was correctly verified") - console.log("Etherscan URL: ", etherscanURL + deployMainnet.polygonZkEVMAddress); - console.log("Path file: ", path.join(__dirname, pathTransparentProxyOZUpgradeDep)); - console.log(); - - // Check proxy Admin - const polygonZkEVMBridgeAdmin = await getProxyAdminAddress(deployMainnet.polygonZkEVMBridgeAddress, mainnetProvider); - const polygonZkEVMAdmin = await getProxyAdminAddress(deployMainnet.polygonZkEVMAddress, mainnetProvider); - const polygonZkEVMGlobalExitRootAdmin = await getProxyAdminAddress(deployMainnet.polygonZkEVMGlobalExitRootAddress, mainnetProvider); - - expect(polygonZkEVMBridgeAdmin).to.be.equal(polygonZkEVMAdmin); - expect(polygonZkEVMAdmin).to.be.equal(polygonZkEVMGlobalExitRootAdmin); - expect(await mainnetProvider.getCode(polygonZkEVMAdmin)) - .to.be.equal(ProxyAdmin.deployedBytecode); - console.log("ProxyAdmin proxy was correctly verified") - console.log("Etherscan URL: ", etherscanURL + polygonZkEVMAdmin); - console.log("Path file: ", path.join(__dirname, pathProxyAdmin)); - console.log(); - - // Assert genesis is the same as the provided in the document - let mainnetPolygonZkVEM = (await ethers.getContractFactory('PolygonZkEVM', mainnetProvider)).attach(deployMainnet.polygonZkEVMAddress); - mainnetPolygonZkVEM = mainnetPolygonZkVEM.connect(mainnetProvider); - expect(await mainnetPolygonZkVEM.batchNumToStateRoot(0)).to.be.equal(deployMainnet.genesisRoot); - console.log("Genesis root was correctly verified:",deployMainnet.genesisRoot) + const mainnetProvider = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}`); + + // Verify contracts + await verifyContract(mainnetProvider, deployMainnet.fflonkVerifierAddress, FflonkVerifier, 'FflonkVerifier'); + await verifyContract(mainnetProvider, deployMainnet.polygonZkEVMDeployerAddress, PolygonZkEVMDeployer, 'PolygonZkEVMDeployer'); + + // Verify Bridge implementation + const polygonZkEVMBridgeImpl = await getImplementationAddress(deployMainnet.polygonZkEVMBridgeAddress, mainnetProvider); + await verifyImplementation(mainnetProvider, polygonZkEVMBridgeImpl, PolygonZkEVMBridge, 'PolygonZkEVMBridge', deployMainnet.polygonZkEVMBridgeAddress); + + // Verify Transparent Proxies + await verifyProxy(mainnetProvider, deployMainnet.polygonZkEVMBridgeAddress, TransparentProxy, 'PolygonZkEVMBridgeAddress proxy'); + + // Verify Timelock contract + await verifyTimelockContract(mainnetProvider); + + // Verify Global Exit Root contract + await verifyGlobalExitRootContract(mainnetProvider); + // Verify PolygonZkEVM contract + await verifyPolygonZkEVMContract(mainnetProvider); + + // Verify Proxy Admin contract + await verifyProxyAdmin(mainnetProvider); + + // Verify Genesis root + await verifyGenesisRoot(mainnetProvider); + + console.log("Verification complete!"); } -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); - -// bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; -// bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; -const adminSlot = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"; -const implSlot = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - -async function getImplementationAddress(proxyAddress, provider) { - const implementationAddress = await provider.getStorageAt(proxyAddress, implSlot); - return `0x${implementationAddress.slice(2 + (32 * 2 - 40))}` + +async function verifyContract(provider, contractAddress, contractArtifact, name) { + expect(await provider.getCode(contractAddress)).to.be.equal(contractArtifact.deployedBytecode); + console.log(`${name} was correctly verified`); + console.log(`Etherscan URL: ${etherscanURL}${contractAddress}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath[name.toLowerCase()])}`); + console.log(); } -async function getProxyAdminAddress(proxyAddress, provider) { - const adminAddress = await provider.getStorageAt(proxyAddress, adminSlot); - return `0x${adminAddress.slice(2 + (32 * 2 - 40))}` +async function verifyImplementation(provider, implAddress, contractArtifact, name, contractAddress) { + expect(await provider.getCode(implAddress)).to.be.equal(contractArtifact.deployedBytecode); + console.log(`${name} implementation was correctly verified`); + console.log(`Etherscan URL: ${etherscanURL}${implAddress}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath[name.toLowerCase()])}`); + console.log(); } + +async function verifyProxy(provider, proxyAddress, proxyArtifact, name) { + expect(await provider.getCode(proxyAddress)).to.be.equal(proxyArtifact.deployedBytecode); + console.log(`${name} was correctly verified`); + console.log(`Etherscan URL: ${etherscanURL}${proxyAddress}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath.transparentProxy)}`); + console.log(); +} + +async function verifyTimelockContract(provider) { + const PolygonZkEVMTimelockFactory = await ethers.getContractFactory('PolygonZkEVMTimelock'); + const timelockAddress = mainnetDeployParameters.timelockAddress; + const minDelayTimelock = mainnetDeployParameters.minDelayTimelock; + + const timelockContract = await PolygonZkEVMTimelockFactory.deploy( + minDelayTimelock, + [timelockAddress], + [timelockAddress], + timelockAddress, + deployMainnet.polygonZkEVMAddress, + ); + await timelockContract.deployed(); + + const deployedBytecodeTimelock = await ethers.provider.getCode(timelockContract.address); + expect(await provider.getCode(deployMainnet.polygonZkEVMTimelockAddress)).to.be.equal(deployedBytecodeTimelock); + console.log("Timelock contract was correctly verified"); + console.log(`Etherscan URL: ${etherscanURL}${deployMainnet.polygonZkEVMTimelockAddress}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath.polygonZkEVMTimelock)}`); + console.log(); +} + +async function verifyGlobalExitRootContract(provider) { + const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory('PolygonZkEVMGlobalExitRoot'); + const globalExitRootContract = await PolygonZkEVMGlobalExitRootFactory.deploy( + deployMainnet.polygonZkEVMAddress, + deployMainnet.polygonZkEVMBridgeAddress + ); + await globalExitRootContract.deployed(); + + const deployedBytecodeGlobalExitRoot = await ethers.provider.getCode(globalExitRootContract.address); + const globalExitRootImpl = await getImplementationAddress(deployMainnet.polygonZkEVMGlobalExitRootAddress, provider); + + expect(await provider.getCode(globalExitRootImpl)).to.be.equal(deployedBytecodeGlobalExitRoot); + console.log("Global Exit Root contract implementation was correctly verified"); + console.log(`Etherscan URL: ${etherscanURL}${globalExitRootImpl}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath.polygonZkEVMGlobalExitRoot)}`); + console.log(); +} + +async function verifyPolygonZkEVMContract(provider) { + const PolygonZkEVMFactory = await ethers.getContractFactory('PolygonZkEVM'); + const polygonZkEVMContract = await PolygonZkEVMFactory.deploy( + deployMainnet.polygonZkEVMGlobalExitRootAddress, + mainnetDeployParameters.maticTokenAddress, + deployMainnet.fflonkVerifierAddress, + deployMainnet.polygonZkEVMBridgeAddress, + mainnetDeployParameters.chainID, + mainnetDeployParameters.forkID, + ); + await polygonZkEVMContract.deployed(); + + const deployedBytecodePolygonZkEVM = await ethers.provider.getCode(polygonZkEVMContract.address); + const polygonZkEVMImpl = await getImplementationAddress(deployMainnet.polygonZkEVMAddress, provider); + + expect(await provider.getCode(polygonZkEVMImpl)).to.be.equal(deployedBytecodePolygonZkEVM); + console.log("PolygonZkEVM contract implementation was correctly verified"); + console.log(`Etherscan URL: ${etherscanURL}${polygonZkEVMImpl}`); + console.log(`Path file: ${path.join(__dirname, artifactsPath.polygonZkEVM)}`); + console.log(); +} + +async function verifyProxyAdmin(provider) { + const proxyAdminAddress = await getProxyAdminAddress(deployMainnet.polygonZkEVMBridgeAddress, provider); + const polygonZkEVMAdmin = await getProxyAdminAddress(deployMainnet.polygonZkEVMAddress, provider); + const globalExitRootAdmin = await getProxyAdminAddress(deployMainnet.polygonZkEVMGlobalExitRootAddress, provider); + + expect(proxyAdminAddress).to.be.equal(polygonZkEVMAdmin); + expect(polygonZkEVMAdmin).to.be.equal(globalExitRootAdmin); + expect(await provider.getCode(polygonZkEVMAdmin)).to.be.equal(ProxyAdmin.deployedBytecode); + + console.log(" diff --git a/verifyMainnetDeployment/verifyTestnetProofVerifier.md b/verifyMainnetDeployment/verifyTestnetProofVerifier.md index bf402ca2..10c90990 100644 --- a/verifyMainnetDeployment/verifyTestnetProofVerifier.md +++ b/verifyMainnetDeployment/verifyTestnetProofVerifier.md @@ -4,7 +4,7 @@ In order to verify the smart contract, you will need a machine with at least 256 In this tutorial we will give instructions for a r6a.8xlarge aws instance. This instance has 16 cores 32 threads, 512GB of SSD. The instance will use Ubuntu 22.04 LTS and the cost of the instance is about 1.82 $/h. This process is quite long, it takes approximately 5-6 hours. -So lets start by launching and instance. +So let's start by launching and instance. ## Basic OS preparation @@ -13,7 +13,7 @@ sudo apt update sudo apt install -y tmux git curl jq ``` -## Tweeking the OS to accept high amount of memory. +## Tweaking the OS to accept high amount of memory. ```bash echo "vm.max_map_count=655300" | sudo tee -a /etc/sysctl.conf @@ -104,7 +104,7 @@ npm install hardhat mkdir -p contracts/verifiers ``` -To generate the same bycode it's important recover exactlly same options used during compilation, we found this information with contract information on etherscan (Settings). +To generate the same bytecode it's important recover exactly same options used during compilation, we found this information with contract information on etherscan (Settings). Copy this information inside the file ~/contract/settings.json, as follows: ```bash @@ -212,7 +212,7 @@ To download bytecode of deployed smartcontract, need the address of smart contra Go to Etherscan or Beaconcha to get transaction bytecode. -Associated with address _0x8d0aAd785905c5c9f942CB18a3AC1e50c4F52786_ found the transacction _0xed0f103dc5e5f5bb8aa5df90a2bfb1949ad41dec8b04e5acc0747dbc1c26e837_. +Associated with address _0x8d0aAd785905c5c9f942CB18a3AC1e50c4F52786_ found the transaction _0xed0f103dc5e5f5bb8aa5df90a2bfb1949ad41dec8b04e5acc0747dbc1c26e837_. - ### Etherscan (https://sepolia.etherscan.io)