diff --git a/hardhat.config.ts b/hardhat.config.ts index a7811945..42b0735a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -116,6 +116,12 @@ module.exports = { ? [process.env['DEVNET_PRIVKEY']] : [], }, + rinkeby: { + url: 'https://rinkeby.infura.io/v3/' + process.env['INFURA_KEY'], + accounts: process.env['DEVNET_PRIVKEY'] + ? [process.env['DEVNET_PRIVKEY']] + : [], + }, arbRinkeby: { url: 'https://rinkeby.arbitrum.io/rpc', accounts: process.env['DEVNET_PRIVKEY'] @@ -168,6 +174,7 @@ module.exports = { goerli: process.env['ETHERSCAN_API_KEY'], sepolia: process.env['ETHERSCAN_API_KEY'], holesky: process.env['ETHERSCAN_API_KEY'], + rinkeby: process.env['ETHERSCAN_API_KEY'], arbitrumOne: process.env['ARBISCAN_API_KEY'], arbitrumTestnet: process.env['ARBISCAN_API_KEY'], nova: process.env['NOVA_ARBISCAN_API_KEY'], diff --git a/scripts/deploymentUtils.ts b/scripts/deploymentUtils.ts index 58ce74b8..f22b0bdb 100644 --- a/scripts/deploymentUtils.ts +++ b/scripts/deploymentUtils.ts @@ -12,6 +12,7 @@ import { ArbOwnerPublic__factory, ArbSys__factory, CacheManager__factory, + EigenDABlobVerifierL1__factory, } from '../build/types' const INIT_CACHE_SIZE = 536870912 @@ -103,17 +104,65 @@ export async function deployContract( return contract } + +// Deploy blob verifier for the EigendaRollupManager +// argument for rollup creator deployment on L1 +// TODO: This logic will be deprecated in the future in favor of +// embedding verifications into the service manager directl +export async function deployBlobVerifierL1( + contractName: string, + signer: any, + constructorArgs: any[] = [], + verify: boolean = true, + overrides?: Overrides +): Promise { + console.log("Deploying contract EigenDA x Arbitrum", contractName) + const eigenDARollupUtils = await deployContract('EigenDARollupUtils', signer, [], verify) + console.log("EigenDARollupUtils deployed at", eigenDARollupUtils.address) + + const eigenda_blob_verifier = await ethers.getContractFactory(contractName, { + libraries: { + EigenDARollupUtils: eigenDARollupUtils.address + } + }) as EigenDABlobVerifierL1__factory + + const connectedFactory: ContractFactory = eigenda_blob_verifier.connect(signer) + + let deploymentArgs = [...constructorArgs] + if (overrides) { + deploymentArgs.push(overrides) + } + + const contract: Contract = await connectedFactory.deploy(...deploymentArgs) + await contract.deployTransaction.wait() + console.log(`New ${contractName} created at address:`, contract.address) + + if (verify) + await verifyContract(contractName, contract.address, constructorArgs) + + return contract +} + // Deploy upgrade executor from imported bytecode export async function deployUpgradeExecutor(signer: any): Promise { + console.log("Deploying contract EigenDA x Arbitrum UpgradeExecutor") const upgradeExecutorFac = await ethers.getContractFactory( UpgradeExecutorABI, UpgradeExecutorBytecode ) const connectedFactory: ContractFactory = upgradeExecutorFac.connect(signer) const upgradeExecutor = await connectedFactory.deploy() + await upgradeExecutor.deployTransaction.wait() + console.log("Upgrade executor deployed at", upgradeExecutor.address) return upgradeExecutor } +const L1ServiceManagers = { + 1: "0x870679E138bCdf293b7Ff14dD44b70FC97e12fc0", // Ethereum + 5: "0xa3b1689Ab85409B15e07d2ED50A6EA9905074Ee5", // Goerli + 17000: "0xD4A7E1Bd8015057293f0D0A557088c286942e84b", // Holesky (testnet) +} + // Function to handle all deployments of core contracts using deployContract function export async function deployAllContracts( signer: any, @@ -121,13 +170,12 @@ export async function deployAllContracts( verify: boolean = true ): Promise> { const isOnArb = await _isRunningOnArbitrum(signer) + const chainId = signer.provider.network.chainId - const eigenDARollupManager = await deployContract( - 'EigenDABlobVerifierL2', - signer, - [], - verify - ) + // If signer is on L1, deploy EigenDABlobVerifierL1 with EigenDAServiceManager as constructor argument + // If signer is on L2, deploy EigenDABlobVerifierL2; blob verifier is used as eigenDARollupManager as part of rollup creation + const eigenDARollupManager = (L1ServiceManagers.hasOwnProperty(chainId)) ? + await deployBlobVerifierL1('EigenDABlobVerifierL1', signer, [L1ServiceManagers[chainId as keyof typeof L1ServiceManagers]], verify) : await deployContract('EigenDABlobVerifierL2', signer, [], verify) const ethBridge = await deployContract('Bridge', signer, [], verify) const reader4844 = isOnArb diff --git a/scripts/local-deployment/createRollup.ts b/scripts/local-deployment/createRollup.ts new file mode 100644 index 00000000..6a27691a --- /dev/null +++ b/scripts/local-deployment/createRollup.ts @@ -0,0 +1,106 @@ +import { ethers } from 'hardhat' +import '@nomiclabs/hardhat-ethers' +import { deployAllContracts, deployBlobVerifierL1 } from '../deploymentUtils' +import { createRollup } from '../rollupCreation' +import { promises as fs } from 'fs' +import { BigNumber } from 'ethers' +import { RollupAdminLogic__factory } from '../../build/types' + +async function main() { + /// read env vars needed for deployment + let childChainName = process.env.CHILD_CHAIN_NAME as string + if (!childChainName) { + throw new Error('CHILD_CHAIN_NAME not set') + } + + let deployerPrivKey = process.env.DEPLOYER_PRIVKEY as string + if (!deployerPrivKey) { + throw new Error('DEPLOYER_PRIVKEY not set') + } + + let parentChainRpc = process.env.PARENT_CHAIN_RPC as string + if (!parentChainRpc) { + throw new Error('PARENT_CHAIN_RPC not set') + } + + if (!process.env.PARENT_CHAIN_ID) { + throw new Error('PARENT_CHAIN_ID not set') + } + + const deployerWallet = new ethers.Wallet( + deployerPrivKey, + new ethers.providers.JsonRpcProvider(parentChainRpc) + ) + + /// get fee token address, if undefined use address(0) to have ETH as fee token + let feeToken = process.env.FEE_TOKEN_ADDRESS as string + if (!feeToken) { + feeToken = ethers.constants.AddressZero + } + console.log('Fee token address:', feeToken) + + const rollupCreatorAddress = process.env.ROLLUP_CREATOR as string + if (!rollupCreatorAddress) { + throw new Error('ROLLUP_CREATOR not set') + } + const rollupCreatorFac = await ethers.getContractFactory('RollupCreator') + const rollupCreator = rollupCreatorFac.attach(rollupCreatorAddress) + + const eigenDARollupManager = process.env.EIGENDA_ROLLUP_MANAGER as string + if (!eigenDARollupManager) { + throw new Error('EIGENDA_ROLLUP_MANAGER not set') + } + + /// Create rollup + const chainId = (await deployerWallet.provider.getNetwork()).chainId + console.log( + 'Create rollup on top of chain', + chainId, + 'using RollupCreator', + rollupCreator.address + ) + const result = await createRollup( + deployerWallet, + true, + rollupCreator.address, + feeToken, + eigenDARollupManager, + ) + + if (!result) { + throw new Error('Rollup creation failed') + } + + const { rollupCreationResult, chainInfo } = result + + /// store deployment address + // chain deployment info + const chainDeploymentInfo = + process.env.CHAIN_DEPLOYMENT_INFO !== undefined + ? process.env.CHAIN_DEPLOYMENT_INFO + : 'deploy.json' + await fs.writeFile( + chainDeploymentInfo, + JSON.stringify(rollupCreationResult, null, 2), + 'utf8' + ) + + // child chain info + chainInfo['chain-name'] = childChainName + const childChainInfo = + process.env.CHILD_CHAIN_INFO !== undefined + ? process.env.CHILD_CHAIN_INFO + : 'l2_chain_info.json' + await fs.writeFile( + childChainInfo, + JSON.stringify([chainInfo], null, 2), + 'utf8' + ) +} + +main() + .then(() => process.exit(0)) + .catch((error: Error) => { + console.error(error) + process.exit(1) + }) diff --git a/scripts/local-deployment/deployBlobVerifierL1.ts b/scripts/local-deployment/deployBlobVerifierL1.ts new file mode 100644 index 00000000..ea481425 --- /dev/null +++ b/scripts/local-deployment/deployBlobVerifierL1.ts @@ -0,0 +1,57 @@ +import { ethers } from 'hardhat' +import '@nomiclabs/hardhat-ethers' +import { deployBlobVerifierL1 } from '../deploymentUtils' +import { promises as fs } from 'fs' + + +async function main() { + /// read env vars needed for deployment + let childChainName = process.env.CHILD_CHAIN_NAME as string + if (!childChainName) { + throw new Error('CHILD_CHAIN_NAME not set') + } + + let deployerPrivKey = process.env.DEPLOYER_PRIVKEY as string + if (!deployerPrivKey) { + throw new Error('DEPLOYER_PRIVKEY not set') + } + + let parentChainRpc = process.env.PARENT_CHAIN_RPC as string + if (!parentChainRpc) { + throw new Error('PARENT_CHAIN_RPC not set') + } + + let eigenDAServiceManagerAddress = process.env.EIGENDA_SERVICE_MANAGER_ADDRESS as string + if (!eigenDAServiceManagerAddress) { + throw new Error('EIGENDA_SERVICE_MANAGER_ADDRESS not set') + } + + if (!process.env.PARENT_CHAIN_ID) { + throw new Error('PARENT_CHAIN_ID not set') + } + + const deployerWallet = new ethers.Wallet( + deployerPrivKey, + new ethers.providers.JsonRpcProvider(parentChainRpc) + ) + + // deploy templates and rollup creator + const blobVerifierL1 = await deployBlobVerifierL1('EigenDABlobVerifierL1', deployerWallet, [eigenDAServiceManagerAddress], true) + console.log('BlobVerifierL1 deployed at', blobVerifierL1.address) + + /// store deployment address + // chain deployment info + const verifierDeploymentInfo = 'blob_verifier_l1_deploy.json' + await fs.writeFile( + verifierDeploymentInfo, + JSON.stringify(blobVerifierL1.address, null, 2), + 'utf8' + ) +} + +main() + .then(() => process.exit(0)) + .catch((error: Error) => { + console.error(error) + process.exit(1) + }) diff --git a/scripts/local-deployment/deployCreator.ts b/scripts/local-deployment/deployCreator.ts new file mode 100644 index 00000000..067a575c --- /dev/null +++ b/scripts/local-deployment/deployCreator.ts @@ -0,0 +1,88 @@ +import { ethers } from 'hardhat' +import '@nomiclabs/hardhat-ethers' +import { deployAllContracts, deployBlobVerifierL1 } from '../deploymentUtils' +import { createRollup } from '../rollupCreation' +import { promises as fs } from 'fs' +import { BigNumber } from 'ethers' +import { RollupAdminLogic__factory } from '../../build/types' + +async function main() { + /// read env vars needed for deployment + let childChainName = process.env.CHILD_CHAIN_NAME as string + if (!childChainName) { + throw new Error('CHILD_CHAIN_NAME not set') + } + + let deployerPrivKey = process.env.DEPLOYER_PRIVKEY as string + if (!deployerPrivKey) { + throw new Error('DEPLOYER_PRIVKEY not set') + } + + let parentChainRpc = process.env.PARENT_CHAIN_RPC as string + if (!parentChainRpc) { + throw new Error('PARENT_CHAIN_RPC not set') + } + + if (!process.env.PARENT_CHAIN_ID) { + throw new Error('PARENT_CHAIN_ID not set') + } + + const deployerWallet = new ethers.Wallet( + deployerPrivKey, + new ethers.providers.JsonRpcProvider(parentChainRpc) + ) + + const maxDataSize = + process.env.MAX_DATA_SIZE !== undefined + ? ethers.BigNumber.from(process.env.MAX_DATA_SIZE) + : ethers.BigNumber.from(117964) + + /// get fee token address, if undefined use address(0) to have ETH as fee token + let feeToken = process.env.FEE_TOKEN_ADDRESS as string + if (!feeToken) { + feeToken = ethers.constants.AddressZero + } + console.log('Fee token address:', feeToken) + + // deploy templates and rollup creator + console.log('Deploy RollupCreator') + + const contracts = await deployAllContracts(deployerWallet, maxDataSize, false) + + console.log('Set templates on the Rollup Creator') + await ( + await contracts.rollupCreator.setTemplates( + contracts.bridgeCreator.address, + contracts.osp.address, + contracts.challengeManager.address, + contracts.rollupAdmin.address, + contracts.rollupUser.address, + contracts.upgradeExecutor.address, + contracts.validatorUtils.address, + contracts.validatorWalletCreator.address, + contracts.deployHelper.address, + { gasLimit: BigNumber.from('300000') } + ) + ).wait() + + console.log('Rollup creator is ready for rollup creation') + + /// store deployment address + // chain deployment info + const chainDeploymentInfo = + process.env.CHAIN_DEPLOYMENT_INFO !== undefined + ? process.env.CHAIN_DEPLOYMENT_INFO + : 'rollupCreatorContracts.json' + await fs.writeFile( + chainDeploymentInfo, + JSON.stringify(contracts, null, 2), + 'utf8' + ) +} + +main() + .then(() => process.exit(0)) + .catch((error: Error) => { + console.error(error) + process.exit(1) + })