diff --git a/app/data/compose/docker-compose-fixturenet-eth.yml b/app/data/compose/docker-compose-fixturenet-eth.yml index 978b983f..bd19c753 100644 --- a/app/data/compose/docker-compose-fixturenet-eth.yml +++ b/app/data/compose/docker-compose-fixturenet-eth.yml @@ -24,6 +24,8 @@ services: env_file: - ../config/fixturenet-eth/fixturenet-eth.env image: cerc/fixturenet-eth-geth:local + volumes: + - fixturenet-geth-accounts:/opt/testnet/build/el healthcheck: test: ["CMD", "nc", "-v", "localhost", "8545"] interval: 30s @@ -79,7 +81,7 @@ services: condition: service_healthy ports: - "8001" - + fixturenet-eth-lighthouse-2: hostname: fixturenet-eth-lighthouse-2 healthcheck: @@ -101,3 +103,6 @@ services: condition: service_started fixturenet-eth-geth-2: condition: service_healthy + +volumes: + fixturenet-geth-accounts: diff --git a/app/data/compose/docker-compose-fixturenet-optimism.yml b/app/data/compose/docker-compose-fixturenet-optimism.yml new file mode 100644 index 00000000..73ba7313 --- /dev/null +++ b/app/data/compose/docker-compose-fixturenet-optimism.yml @@ -0,0 +1,28 @@ +version: '3.7' + +services: + + fixturenet-optimism-contracts: + hostname: fixturenet-optimism-contracts + depends_on: + fixturenet-eth-geth-1: + condition: service_healthy + image: cerc/fixturenet-optimism:local + environment: + CHAIN_ID: 1212 + L1_RPC: "http://fixturenet-eth-geth-1:8545" + command: ["sh", "run.sh"] + volumes: + - ../config/fixturenet-optimism/optimism-contracts/rekey-json.ts:/app/packages/contracts-bedrock/tasks/rekey-json.ts + - ../config/fixturenet-optimism/optimism-contracts/send-balance.ts:/app/packages/contracts-bedrock/tasks/send-balance.ts + - ../config/fixturenet-optimism/optimism-contracts/update-config.js:/app/packages/contracts-bedrock/update-config.js + - ../config/fixturenet-optimism/optimism-contracts/run.sh:/app/packages/contracts-bedrock/run.sh + - fixturenet-geth-accounts:/geth-accounts + - l2-accounts:/l2-accounts + # TODO: Add healthcheck + # healthcheck: + +volumes: + l2-accounts: + # TODO: Required? + # fixturenet-geth-accounts: diff --git a/app/data/config/fixturenet-optimism/optimism-contracts/rekey-json.ts b/app/data/config/fixturenet-optimism/optimism-contracts/rekey-json.ts new file mode 100644 index 00000000..78312499 --- /dev/null +++ b/app/data/config/fixturenet-optimism/optimism-contracts/rekey-json.ts @@ -0,0 +1,28 @@ +import fs from 'fs' + +import { task } from 'hardhat/config' +import { hdkey } from 'ethereumjs-wallet' +import * as bip39 from 'bip39' + +task('rekey-json', 'Generates a new set of keys for a test network') + .addParam('output', 'JSON file to output accounts to') + .setAction(async ({ output: outputFile }) => { + const mnemonic = bip39.generateMnemonic() + const pathPrefix = "m/44'/60'/0'/0" + const labels = ['Admin', 'Proposer', 'Batcher', 'Sequencer'] + const hdwallet = hdkey.fromMasterSeed(await bip39.mnemonicToSeed(mnemonic)) + + const output = {} + + for (let i = 0; i < labels.length; i++) { + const label = labels[i] + const wallet = hdwallet.derivePath(`${pathPrefix}/${i}`).getWallet() + const addr = '0x' + wallet.getAddress().toString('hex') + const pk = wallet.getPrivateKey().toString('hex') + + output[label] = { address: addr, privateKey: pk } + } + + fs.writeFileSync(outputFile, JSON.stringify(output, null, 2)) + console.log(`L2 account keys written to ${outputFile}`) + }) diff --git a/app/data/config/fixturenet-optimism/optimism-contracts/run.sh b/app/data/config/fixturenet-optimism/optimism-contracts/run.sh new file mode 100755 index 00000000..a03d5ba0 --- /dev/null +++ b/app/data/config/fixturenet-optimism/optimism-contracts/run.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Append tasks/index.ts file +echo "import './rekey-json'" >> tasks/index.ts +echo "import './send-balance'" >> tasks/index.ts + +# Update the chainId in the hardhat config +sed -i "/getting-started/ {n; s/.*chainId.*/ chainId: $CHAIN_ID,/}" hardhat.config.ts + +# Generate the L2 account addresses +yarn hardhat rekey-json --output /l2-accounts/keys.json + +# Read JSON file into variable +KEYS_JSON=$(cat /l2-accounts/keys.json) + +# Parse JSON into variables +ADMIN_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Admin.address') +ADMIN_PRIV_KEY=$(echo "$KEYS_JSON" | jq -r '.Admin.privateKey') +PROPOSER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Admin.address') +BATCHER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Admin.address') +SEQUENCER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Admin.address') + +# Read the private key of a L1 account +L1_PRIV_KEY=$(head -n 1 /geth-accounts/accounts.csv | cut -d ',' -f 3) + +# Send balances to the above L2 addresses +yarn hardhat send-balance --to "${ADMIN_ADDRESS}" --amount 2 --private-key "${L1_PRIV_KEY}" --network getting-started +yarn hardhat send-balance --to "${PROPOSER_ADDRESS}" --amount 5 --private-key "${L1_PRIV_KEY}" --network getting-started +yarn hardhat send-balance --to "${BATCHER_ADDRESS}" --amount 1000 --private-key "${L1_PRIV_KEY}" --network getting-started + +echo "Balances sent to L2 accounts" + +# Select a finalized L1 block as the starting point for roll ups +CAST_OUTPUT=$(cast block finalized --rpc-url "$L1_RPC") +L1_BLOCKHASH=$(echo "$CAST_OUTPUT" | awk '/hash/{print $2}') +L1_BLOCKTIMESTAMP=$(echo "$CAST_OUTPUT" | awk '/timestamp/{print $2}') + +# Update the deployment config +sed -i 's/"l2OutputOracleStartingTimestamp": TIMESTAMP/"l2OutputOracleStartingTimestamp": '"$L1_BLOCKTIMESTAMP"'/g' deploy-config/getting-started.json +jq --arg chainid "$CHAIN_ID" '.l1ChainID = ($chainid | tonumber)' deploy-config/getting-started.json > tmp.json && mv tmp.json deploy-config/getting-started.json + +node update-config.js deploy-config/getting-started.json "$ADMIN_ADDRESS" "$PROPOSER_ADDRESS" "$BATCHER_ADDRESS" "$SEQUENCER_ADDRESS" "$L1_BLOCKHASH" + +echo "Updated the deployment config" + +# Create a .env file +echo "L1_RPC=$L1_RPC" > .env +echo "PRIVATE_KEY_DEPLOYER=$ADMIN_PRIV_KEY" >> .env + +# Deploy the L1 smart contracts +yarn hardhat deploy --network getting-started + +echo "Deployed the L1 smart contracts" diff --git a/app/data/config/fixturenet-optimism/optimism-contracts/send-balance.ts b/app/data/config/fixturenet-optimism/optimism-contracts/send-balance.ts new file mode 100644 index 00000000..f5c3c688 --- /dev/null +++ b/app/data/config/fixturenet-optimism/optimism-contracts/send-balance.ts @@ -0,0 +1,31 @@ +import fs from 'fs' + +import { task } from 'hardhat/config' +import '@nomiclabs/hardhat-ethers' + +task('send-balance', 'Sends Ether to a specified Ethereum account') + .addParam('to', 'The Ethereum address to send Ether to') + .addParam('amount', 'The amount of Ether to send, in Ether') + .addParam('privateKey', 'The private key of the sender') + .setAction(async ({ to, amount, privateKey }, { ethers }) => { + const fileContent = fs.readFileSync('/l2-accounts/keys.json', 'utf-8') + const keySet = JSON.parse(fileContent) + + // Get the dest account address from the json file if key present + let address: string = to + if (to in keySet) { + address = keySet[to].address + } + + // Open the wallet using sender's private key + const wallet = new ethers.Wallet(privateKey, ethers.provider) + + // Send amount to the specified address + const tx = await wallet.sendTransaction({ + to: address, + value: ethers.utils.parseEther(amount), + }) + + console.log(`Balance sent to: ${address}, from: ${wallet.address}`) + console.log(`Transaction hash: ${tx.hash}`) + }) diff --git a/app/data/config/fixturenet-optimism/optimism-contracts/update-config.js b/app/data/config/fixturenet-optimism/optimism-contracts/update-config.js new file mode 100644 index 00000000..8a6c09d4 --- /dev/null +++ b/app/data/config/fixturenet-optimism/optimism-contracts/update-config.js @@ -0,0 +1,36 @@ +const fs = require('fs') + +// Get the command-line argument +const configFile = process.argv[2] +const adminAddress = process.argv[3] +const proposerAddress = process.argv[4] +const batcherAddress = process.argv[5] +const sequencerAddress = process.argv[6] +const blockHash = process.argv[7] + +// Read the JSON file +const configData = fs.readFileSync(configFile) +const configObj = JSON.parse(configData) + +// Update the finalSystemOwner property with the ADMIN_ADDRESS value +configObj.finalSystemOwner = + configObj.portalGuardian = + configObj.controller = + configObj.l2OutputOracleChallenger = + configObj.proxyAdminOwner = + configObj.baseFeeVaultRecipient = + configObj.l1FeeVaultRecipient = + configObj.sequencerFeeVaultRecipient = + configObj.governanceTokenOwner = + adminAddress + +configObj.l2OutputOracleProposer = proposerAddress + +configObj.batchSenderAddress = batcherAddress + +configObj.p2pSequencerAddress = sequencerAddress + +configObj.l1StartingBlockTag = blockHash + +// Write the updated JSON object back to the file +fs.writeFileSync(configFile, JSON.stringify(configObj, null, 2))