Commit bd30275b authored by Diederik Loerakker's avatar Diederik Loerakker Committed by GitHub

feat(contracts-bedrock,sdk): deploy config typing, hivenet (#3187)

* feat(contracts-bedrock,sdk): deploy config typing, hivenet

* bedrock: op-batcher,op-node,op-proposer flags consistency

* contracts-bedrock: hardhat deploy config review feedback

* contracts-bedrock: lint fixes

* contracts-bedrock: fix chain IDs in deploy configs

* ops-bedrock: remove l1 genesis timestamp env var
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
Co-authored-by: default avatarmergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
parent a095d544
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
) )
const envVarPrefix = "BATCH_SUBMITTER_" const envVarPrefix = "OP_BATCHER_"
func prefixEnvVar(name string) string { func prefixEnvVar(name string) string {
return envVarPrefix + name return envVarPrefix + name
...@@ -17,19 +17,19 @@ var ( ...@@ -17,19 +17,19 @@ var (
Name: "l1-eth-rpc", Name: "l1-eth-rpc",
Usage: "HTTP provider URL for L1", Usage: "HTTP provider URL for L1",
Required: true, Required: true,
EnvVar: "L1_ETH_RPC", EnvVar: prefixEnvVar("L1_ETH_RPC"),
} }
L2EthRpcFlag = cli.StringFlag{ L2EthRpcFlag = cli.StringFlag{
Name: "l2-eth-rpc", Name: "l2-eth-rpc",
Usage: "HTTP provider URL for L2 execution engine", Usage: "HTTP provider URL for L2 execution engine",
Required: true, Required: true,
EnvVar: "L2_ETH_RPC", EnvVar: prefixEnvVar("L2_ETH_RPC"),
} }
RollupRpcFlag = cli.StringFlag{ RollupRpcFlag = cli.StringFlag{
Name: "rollup-rpc", Name: "rollup-rpc",
Usage: "HTTP provider URL for Rollup node", Usage: "HTTP provider URL for Rollup node",
Required: true, Required: true,
EnvVar: "ROLLUP_RPC", EnvVar: prefixEnvVar("ROLLUP_RPC"),
} }
MinL1TxSizeBytesFlag = cli.Uint64Flag{ MinL1TxSizeBytesFlag = cli.Uint64Flag{
Name: "min-l1-tx-size-bytes", Name: "min-l1-tx-size-bytes",
...@@ -105,13 +105,13 @@ var ( ...@@ -105,13 +105,13 @@ var (
/* Optional Flags */ /* Optional Flags */
LogLevelFlag = cli.StringFlag{ LogLevelFlag = cli.StringFlag{
Name: "log-level", Name: "log.level",
Usage: "The lowest log level that will be output", Usage: "The lowest log level that will be output",
Value: "info", Value: "info",
EnvVar: prefixEnvVar("LOG_LEVEL"), EnvVar: prefixEnvVar("LOG_LEVEL"),
} }
LogTerminalFlag = cli.BoolFlag{ LogTerminalFlag = cli.BoolFlag{
Name: "log-terminal", Name: "log.terminal",
Usage: "If true, outputs logs in terminal format, otherwise prints " + Usage: "If true, outputs logs in terminal format, otherwise prints " +
"in JSON format.", "in JSON format.",
EnvVar: prefixEnvVar("LOG_TERMINAL"), EnvVar: prefixEnvVar("LOG_TERMINAL"),
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
// Flags // Flags
const envVarPrefix = "ROLLUP_NODE_" const envVarPrefix = "OP_NODE_"
func prefixEnvVar(name string) string { func prefixEnvVar(name string) string {
return envVarPrefix + name return envVarPrefix + name
......
...@@ -45,9 +45,9 @@ type Config struct { ...@@ -45,9 +45,9 @@ type Config struct {
// Note: below addresses are part of the block-derivation process, // Note: below addresses are part of the block-derivation process,
// and required to be the same network-wide to stay in consensus. // and required to be the same network-wide to stay in consensus.
// L2 address receiving all L2 transaction fees // L2 address used to send all priority fees to, also known as the coinbase address in the block.
FeeRecipientAddress common.Address `json:"fee_recipient_address"` FeeRecipientAddress common.Address `json:"fee_recipient_address"`
// L1 address that batches are sent to // L1 address that batches are sent to.
BatchInboxAddress common.Address `json:"batch_inbox_address"` BatchInboxAddress common.Address `json:"batch_inbox_address"`
// Acceptable batch-sender address // Acceptable batch-sender address
BatchSenderAddress common.Address `json:"batch_sender_address"` BatchSenderAddress common.Address `json:"batch_sender_address"`
......
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
) )
const envVarPrefix = "OUTPUT_SUBMITTER_" const envVarPrefix = "OP_PROPOSER_"
func prefixEnvVar(name string) string { func prefixEnvVar(name string) string {
return envVarPrefix + name return envVarPrefix + name
...@@ -17,25 +17,25 @@ var ( ...@@ -17,25 +17,25 @@ var (
Name: "l1-eth-rpc", Name: "l1-eth-rpc",
Usage: "HTTP provider URL for L1", Usage: "HTTP provider URL for L1",
Required: true, Required: true,
EnvVar: "L1_ETH_RPC", EnvVar: prefixEnvVar("L1_ETH_RPC"),
} }
L2EthRpcFlag = cli.StringFlag{ L2EthRpcFlag = cli.StringFlag{
Name: "l2-eth-rpc", Name: "l2-eth-rpc",
Usage: "HTTP provider URL for L2", Usage: "HTTP provider URL for L2",
Required: true, Required: true,
EnvVar: "L2_ETH_RPC", EnvVar: prefixEnvVar("L2_ETH_RPC"),
} }
RollupRpcFlag = cli.StringFlag{ RollupRpcFlag = cli.StringFlag{
Name: "rollup-rpc", Name: "rollup-rpc",
Usage: "HTTP provider URL for the rollup node", Usage: "HTTP provider URL for the rollup node",
Required: true, Required: true,
EnvVar: "ROLLUP_RPC", EnvVar: prefixEnvVar("ROLLUP_RPC"),
} }
L2OOAddressFlag = cli.StringFlag{ L2OOAddressFlag = cli.StringFlag{
Name: "l2oo-address", Name: "l2oo-address",
Usage: "Address of the L2OutputOracle contract", Usage: "Address of the L2OutputOracle contract",
Required: true, Required: true,
EnvVar: "L2OO_ADDRESS", EnvVar: prefixEnvVar("L2OO_ADDRESS"),
} }
PollIntervalFlag = cli.DurationFlag{ PollIntervalFlag = cli.DurationFlag{
Name: "poll-interval", Name: "poll-interval",
...@@ -87,13 +87,13 @@ var ( ...@@ -87,13 +87,13 @@ var (
/* Optional Flags */ /* Optional Flags */
LogLevelFlag = cli.StringFlag{ LogLevelFlag = cli.StringFlag{
Name: "log-level", Name: "log.level",
Usage: "The lowest log level that will be output", Usage: "The lowest log level that will be output",
Value: "info", Value: "info",
EnvVar: prefixEnvVar("LOG_LEVEL"), EnvVar: prefixEnvVar("LOG_LEVEL"),
} }
LogTerminalFlag = cli.BoolFlag{ LogTerminalFlag = cli.BoolFlag{
Name: "log-terminal", Name: "log.terminal",
Usage: "If true, outputs logs in terminal format, otherwise prints " + Usage: "If true, outputs logs in terminal format, otherwise prints " +
"in JSON format.", "in JSON format.",
EnvVar: prefixEnvVar("LOG_TERMINAL"), EnvVar: prefixEnvVar("LOG_TERMINAL"),
......
...@@ -57,20 +57,13 @@ function wait_up { ...@@ -57,20 +57,13 @@ function wait_up {
mkdir -p ./.devnet mkdir -p ./.devnet
if [ ! -f ./.devnet/rollup.json ]; then
L1_GENESIS_TIMESTAMP=$(date +%s | xargs printf "0x%x")
else
L1_GENESIS_TIMESTAMP=$(jq '.timestamp' < .devnet/genesis-l1.json)
fi
# Regenerate the L1 genesis file if necessary. The existence of the genesis # Regenerate the L1 genesis file if necessary. The existence of the genesis
# file is used to determine if we need to recreate the devnet's state folder. # file is used to determine if we need to recreate the devnet's state folder.
if [ ! -f ./.devnet/genesis-l1.json ]; then if [ ! -f ./.devnet/genesis-l1.json ]; then
echo "Regenerating L1 genesis." echo "Regenerating L1 genesis."
( (
cd $CONTRACTS_BEDROCK cd $CONTRACTS_BEDROCK
L1_GENESIS_TIMESTAMP=$L1_GENESIS_TIMESTAMP npx hardhat genesis-l1 \ npx hardhat --network $NETWORK genesis-l1 --outfile genesis-l1.json
--outfile genesis-l1.json
mv genesis-l1.json ../../.devnet/genesis-l1.json mv genesis-l1.json ../../.devnet/genesis-l1.json
) )
fi fi
...@@ -89,7 +82,7 @@ if [ ! -d $CONTRACTS_BEDROCK/deployments/$NETWORK ]; then ...@@ -89,7 +82,7 @@ if [ ! -d $CONTRACTS_BEDROCK/deployments/$NETWORK ]; then
( (
echo "Deploying contracts." echo "Deploying contracts."
cd $CONTRACTS_BEDROCK cd $CONTRACTS_BEDROCK
L1_GENESIS_TIMESTAMP=$L1_GENESIS_TIMESTAMP yarn hardhat --network $NETWORK deploy yarn hardhat --network $NETWORK deploy
) )
else else
echo "Contracts already deployed, skipping." echo "Contracts already deployed, skipping."
...@@ -99,7 +92,7 @@ if [ ! -f ./.devnet/genesis-l2.json ]; then ...@@ -99,7 +92,7 @@ if [ ! -f ./.devnet/genesis-l2.json ]; then
( (
echo "Creating L2 genesis file." echo "Creating L2 genesis file."
cd $CONTRACTS_BEDROCK cd $CONTRACTS_BEDROCK
L1_GENESIS_TIMESTAMP=$L1_GENESIS_TIMESTAMP npx hardhat --network $NETWORK genesis-l2 npx hardhat --network $NETWORK genesis-l2
mv genesis.json ../../.devnet/genesis-l2.json mv genesis.json ../../.devnet/genesis-l2.json
echo "Created L2 genesis." echo "Created L2 genesis."
) )
...@@ -120,7 +113,7 @@ if [ ! -f ./.devnet/rollup.json ]; then ...@@ -120,7 +113,7 @@ if [ ! -f ./.devnet/rollup.json ]; then
( (
echo "Building rollup config..." echo "Building rollup config..."
cd $CONTRACTS_BEDROCK cd $CONTRACTS_BEDROCK
L1_GENESIS_TIMESTAMP=$L1_GENESIS_TIMESTAMP npx hardhat --network $NETWORK rollup-config npx hardhat --network $NETWORK rollup-config
mv rollup.json ../../.devnet/rollup.json mv rollup.json ../../.devnet/rollup.json
) )
else else
......
...@@ -87,18 +87,18 @@ services: ...@@ -87,18 +87,18 @@ services:
ports: ports:
- "6062:6060" - "6062:6060"
environment: environment:
L1_ETH_RPC: http://l1:8545 OP_PROPOSER_L1_ETH_RPC: http://l1:8545
L2_ETH_RPC: http://l2:8545 OP_PROPOSER_L2_ETH_RPC: http://l2:8545
ROLLUP_RPC: http://op-node:8545 OP_PROPOSER_ROLLUP_RPC: http://op-node:8545
OUTPUT_SUBMITTER_POLL_INTERVAL: 1s OP_PROPOSER_POLL_INTERVAL: 1s
OUTPUT_SUBMITTER_NUM_CONFIRMATIONS: 1 OP_PROPOSER_NUM_CONFIRMATIONS: 1
OUTPUT_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 OP_PROPOSER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3
OUTPUT_SUBMITTER_RESUBMISSION_TIMEOUT: 30s OP_PROPOSER_RESUBMISSION_TIMEOUT: 30s
OUTPUT_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk OP_PROPOSER_MNEMONIC: test test test test test test test test test test test junk
OUTPUT_SUBMITTER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" OP_PROPOSER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1"
OUTPUT_SUBMITTER_LOG_TERMINAL: "true" OP_PROPOSER_LOG_TERMINAL: "true"
L2OO_ADDRESS: "${L2OO_ADDRESS}" OP_PROPOSER_L2OO_ADDRESS: "${L2OO_ADDRESS}"
OUTPUT_SUBMITTER_PPROF_ENABLED: "true" OP_PROPOSER_PPROF_ENABLED: "true"
op-batcher: op-batcher:
depends_on: depends_on:
...@@ -111,22 +111,22 @@ services: ...@@ -111,22 +111,22 @@ services:
ports: ports:
- "6061:6060" - "6061:6060"
environment: environment:
L1_ETH_RPC: http://l1:8545 OP_BATCHER_L1_ETH_RPC: http://l1:8545
L2_ETH_RPC: http://l2:8545 OP_BATCHER_L2_ETH_RPC: http://l2:8545
ROLLUP_RPC: http://op-node:8545 OP_BATCHER_ROLLUP_RPC: http://op-node:8545
BATCH_SUBMITTER_MIN_L1_TX_SIZE_BYTES: 1 OP_BATCHER_MIN_L1_TX_SIZE_BYTES: 1
BATCH_SUBMITTER_MAX_L1_TX_SIZE_BYTES: 120000 OP_BATCHER_MAX_L1_TX_SIZE_BYTES: 120000
BATCH_SUBMITTER_CHANNEL_TIMEOUT: 40 OP_BATCHER_CHANNEL_TIMEOUT: 40
BATCH_SUBMITTER_POLL_INTERVAL: 1s OP_BATCHER_POLL_INTERVAL: 1s
BATCH_SUBMITTER_NUM_CONFIRMATIONS: 1 OP_BATCHER_NUM_CONFIRMATIONS: 1
BATCH_SUBMITTER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3
BATCH_SUBMITTER_RESUBMISSION_TIMEOUT: 30s OP_BATCHER_RESUBMISSION_TIMEOUT: 30s
BATCH_SUBMITTER_MNEMONIC: test test test test test test test test test test test junk OP_BATCHER_MNEMONIC: test test test test test test test test test test test junk
BATCH_SUBMITTER_SEQUENCER_HD_PATH: "m/44'/60'/0'/0/2" OP_BATCHER_SEQUENCER_HD_PATH: "m/44'/60'/0'/0/2"
BATCH_SUBMITTER_SEQUENCER_GENESIS_HASH: "${SEQUENCER_GENESIS_HASH}" OP_BATCHER_SEQUENCER_GENESIS_HASH: "${SEQUENCER_GENESIS_HASH}"
BATCH_SUBMITTER_SEQUENCER_BATCH_INBOX_ADDRESS: "${SEQUENCER_BATCH_INBOX_ADDRESS}" OP_BATCHER_SEQUENCER_BATCH_INBOX_ADDRESS: "${SEQUENCER_BATCH_INBOX_ADDRESS}"
BATCH_SUBMITTER_LOG_TERMINAL: "true" OP_BATCHER_LOG_TERMINAL: "true"
BATCH_SUBMITTER_PPROF_ENABLED: "true" OP_BATCHER_PPROF_ENABLED: "true"
stateviz: stateviz:
build: build:
......
...@@ -113,7 +113,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -113,7 +113,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
* @param _historicalTotalBlocks Number of blocks preceding this L2 chain. * @param _historicalTotalBlocks Number of blocks preceding this L2 chain.
* @param _startingBlockNumber The number of the first L2 block. * @param _startingBlockNumber The number of the first L2 block.
* @param _startingTimestamp The timestamp of the first L2 block. * @param _startingTimestamp The timestamp of the first L2 block.
* @param _l2BlockTime The timestamp of the first L2 block. * @param _l2BlockTime The time per L2 block, in seconds.
* @param _proposer The address of the proposer. * @param _proposer The address of the proposer.
* @param _owner The address of the owner. * @param _owner The address of the owner.
*/ */
......
import { ethers } from 'ethers'
const { env } = process
const l1GenesisTimestamp =
typeof env.L1_GENESIS_TIMESTAMP === 'string'
? ethers.BigNumber.from(env.L1_GENESIS_TIMESTAMP).toNumber()
: Math.floor(Date.now() / 1000)
const config = { const config = {
submissionInterval: 20, // general
genesisOutput: ethers.constants.HashZero,
historicalBlocks: 0,
l1StartingBlockTag: 'earliest', l1StartingBlockTag: 'earliest',
startingBlockNumber: 0, l1ChainID: 900,
l2ChainID: 901,
l2BlockTime: 2, l2BlockTime: 2,
l1GenesisTimestamp, // rollup
sequencerAddress: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', maxSequencerDrift: 100,
sequencerWindowSize: 4,
l2CrossDomainMessengerOwner: ethers.constants.AddressZero, channelTimeout: 40,
gasPriceOracleOwner: ethers.constants.AddressZero, p2pSequencerAddress: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc',
gasPriceOracleOverhead: 2100, optimismL2FeeRecipient: '0xd9c09e21b57c98e58a80552c170989b426766aa7',
gasPriceOracleScalar: 1000000, batchInboxAddress: '0xff00000000000000000000000000000000000000',
gasPriceOracleDecimals: 6, batchSenderAddress: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
l1BlockInitialNumber: 0, // output oracle
l1BlockInitialTimestamp: 0, l2OutputOracleSubmissionInterval: 20,
l1BlockInitialBasefee: 10, l2OutputOracleStartingTimestamp: -1, // based on L1 starting tag instead
l1BlockInitialHash: ethers.constants.HashZero, l2OutputOracleProposer: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
l1BlockInitialSequenceNumber: 0, l2OutputOracleOwner: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
proxyAdmin: '0x829BD824B016326A401d083B33D092293333A830', // l1
genesisBlockExtradata: ethers.utils.hexConcat([ l1BlockTime: 15,
ethers.constants.HashZero, cliqueSignerAddress: '0xca062b0fd91172d89bcd4bb084ac4e21972cc467',
'0xca062b0fd91172d89bcd4bb084ac4e21972cc467',
ethers.utils.hexZeroPad('0x', 65),
]),
genesisBlockGasLimit: ethers.BigNumber.from(15000000).toHexString(),
genesisBlockChainid: 901, // l2
fundDevAccounts: true,
optimismBaseFeeRecipient: '0xBcd4042DE499D14e55001CcbB24a551F3b954096', optimismBaseFeeRecipient: '0xBcd4042DE499D14e55001CcbB24a551F3b954096',
optimismL1FeeRecipient: '0x71bE63f3384f5fb98995898A86B02Fb2426c5788', optimismL1FeeRecipient: '0x71bE63f3384f5fb98995898A86B02Fb2426c5788',
proxyAdmin: '0x829BD824B016326A401d083B33D092293333A830',
fundDevAccounts: true,
p2pSequencerAddress: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc', // deploying
deploymentWaitConfirmations: 1, deploymentWaitConfirmations: 1,
maxSequencerDrift: 100,
sequencerWindowSize: 4,
channelTimeout: 40,
outputOracleOwner: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
optimismL2FeeRecipient: '0xd9c09e21b57c98e58a80552c170989b426766aa7',
batchSenderAddress: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
} }
export default config export default config
import { ethers } from 'ethers'
const sequencerAddress = '0x6c23a0dcdfc44b7a57bed148de598895e398d984'
const l1StartingBlockTag = const l1StartingBlockTag =
'0xafce66a0a2446856112e4069b275ad32b1f4a607888f9c4c59eddf9be81f8670' '0xafce66a0a2446856112e4069b275ad32b1f4a607888f9c4c59eddf9be81f8670'
const config = { const config = {
submissionInterval: 6, // general
genesisOutput: ethers.constants.HashZero,
historicalBlocks: 0,
startingBlockNumber: 0,
l2BlockTime: 2,
l1StartingBlockTag, l1StartingBlockTag,
sequencerAddress, l1ChainID: 5,
l2ChainID: 111,
l2CrossDomainMessengerOwner: ethers.constants.AddressZero, l2BlockTime: 2,
gasPriceOracleOwner: ethers.constants.AddressZero,
gasPriceOracleOverhead: 2100,
gasPriceOracleScalar: 1000000,
gasPriceOracleDecimals: 6,
l1BlockInitialNumber: 0,
l1BlockInitialTimestamp: 0,
l1BlockInitialBasefee: 10,
l1BlockInitialHash: ethers.constants.HashZero,
l1BlockInitialSequenceNumber: 0,
genesisBlockExtradata: ethers.utils.hexConcat([
ethers.constants.HashZero,
sequencerAddress,
ethers.utils.hexZeroPad('0x', 65),
]),
genesisBlockGasLimit: ethers.BigNumber.from(15000000).toHexString(),
genesisBlockChainid: 111,
fundDevAccounts: true,
p2pSequencerAddress: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc',
deploymentWaitConfirmations: 1,
// rollup
maxSequencerDrift: 1000, maxSequencerDrift: 1000,
sequencerWindowSize: 120, sequencerWindowSize: 120,
channelTimeout: 120, channelTimeout: 120,
p2pSequencerAddress: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc',
optimismL2FeeRecipient: '0x26862c200bd48c19f39d9e1cd88a3b439611d911',
batchInboxAddress: '0xff00000000000000000000000000000000000002',
batchSenderAddress: '0xa11d2b908470e17923fff184d48269bebbd9b2a5',
proxyAdmin: '0xe584e1b833ca80020130b1b69f84f90479076168', // output oracle
l2OutputOracleSubmissionInterval: 6,
l2OutputOracleStartingTimestamp: -1, // based on L1 starting tag instead
l2OutputOracleProposer: '0x6c23a0dcdfc44b7a57bed148de598895e398d984',
l2OutputOracleOwner: '0x6925b8704ff96dee942623d6fb5e946ef5884b63',
// l2
optimismBaseFeeRecipient: '0xf116a24056b647e3211d095c667e951536cdebaa', optimismBaseFeeRecipient: '0xf116a24056b647e3211d095c667e951536cdebaa',
optimismL1FeeRecipient: '0xc731837b696ca3d9720d23336925368ceaa58f83', optimismL1FeeRecipient: '0xc731837b696ca3d9720d23336925368ceaa58f83',
optimismL2FeeRecipient: '0x26862c200bd48c19f39d9e1cd88a3b439611d911', proxyAdmin: '0xe584e1b833ca80020130b1b69f84f90479076168',
outputOracleOwner: '0x6925b8704ff96dee942623d6fb5e946ef5884b63', fundDevAccounts: true,
batchSenderAddress: '0xa11d2b908470e17923fff184d48269bebbd9b2a5',
// deploying
deploymentWaitConfirmations: 1,
} }
export default config export default config
import { ethers } from 'ethers'
const { env } = process
const l1GenesisTimestamp =
typeof env.L1_GENESIS_TIMESTAMP === 'string'
? ethers.BigNumber.from(env.L1_GENESIS_TIMESTAMP).toNumber()
: Math.floor(Date.now() / 1000)
const config = { const config = {
submissionInterval: 6, // general
genesisOutput: ethers.constants.HashZero,
historicalBlocks: 0,
startingBlockNumber: 0,
l1StartingBlockTag: 'earliest', l1StartingBlockTag: 'earliest',
l1ChainID: 900,
l2ChainID: 901,
l2BlockTime: 2, l2BlockTime: 2,
l1GenesisTimestamp,
sequencerAddress: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // rollup
maxSequencerDrift: 10, maxSequencerDrift: 10,
sequencerWindowSize: 4, sequencerWindowSize: 4,
channelTimeout: 40, channelTimeout: 40,
outputOracleOwner: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', p2pSequencerAddress: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc',
optimismL2FeeRecipient: '0xd9c09e21b57c98e58a80552c170989b426766aa7',
batchInboxAddress: '0xff00000000000000000000000000000000000000',
batchSenderAddress: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
// output oracle
l2OutputOracleSubmissionInterval: 6,
l2OutputOracleStartingTimestamp: -1, // based on L1 starting tag instead
l2OutputOracleProposer: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
l2OutputOracleOwner: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
// l1: all defaults
// l2
proxyAdmin: 0x0000000000000000000000000000000000000000,
fundDevAccounts: true, fundDevAccounts: true,
// deploying
deploymentWaitConfirmations: 1,
} }
export default config export default config
...@@ -10,10 +10,16 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -10,10 +10,16 @@ const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
const { deployConfig } = hre const { deployConfig } = hre
let deployL2StartingTimestamp = deployConfig.l2OutputOracleStartingTimestamp
if (deployL2StartingTimestamp < 0) {
const l1 = hre.ethers.provider const l1 = hre.ethers.provider
const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag) const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag)
if (l1StartingBlock === null) { if (l1StartingBlock === null) {
throw new Error(`Cannot fetch block tag ${deployConfig.l1StartingBlockTag}`) throw new Error(
`Cannot fetch block tag ${deployConfig.l1StartingBlockTag}`
)
}
deployL2StartingTimestamp = l1StartingBlock.timestamp
} }
await deploy('L2OutputOracleProxy', { await deploy('L2OutputOracleProxy', {
...@@ -27,14 +33,14 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -27,14 +33,14 @@ const deployFn: DeployFunction = async (hre) => {
await deploy('L2OutputOracle', { await deploy('L2OutputOracle', {
from: deployer, from: deployer,
args: [ args: [
deployConfig.submissionInterval, deployConfig.l2OutputOracleSubmissionInterval,
deployConfig.genesisOutput, deployConfig.l2OutputOracleGenesisL2Output,
deployConfig.historicalBlocks, deployConfig.l2OutputOracleHistoricalTotalBlocks,
deployConfig.startingBlockNumber, deployConfig.l2OutputOracleStartingBlockNumber,
l1StartingBlock.timestamp, deployL2StartingTimestamp,
deployConfig.l2BlockTime, deployConfig.l2BlockTime,
deployConfig.sequencerAddress, deployConfig.l2OutputOracleProposer,
deployConfig.outputOracleOwner, deployConfig.l2OutputOracleOwner,
], ],
log: true, log: true,
waitConfirmations: deployConfig.deploymentWaitConfirmations, waitConfirmations: deployConfig.deploymentWaitConfirmations,
...@@ -54,34 +60,44 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -54,34 +60,44 @@ const deployFn: DeployFunction = async (hre) => {
L2OutputOracle.interface.encodeFunctionData( L2OutputOracle.interface.encodeFunctionData(
'initialize(bytes32,uint256,address,address)', 'initialize(bytes32,uint256,address,address)',
[ [
deployConfig.genesisOutput, deployConfig.l2OutputOracleGenesisL2Output,
deployConfig.startingBlockNumber, deployConfig.l2OutputOracleStartingBlockNumber,
deployConfig.sequencerAddress, deployConfig.l2OutputOracleProposer,
deployConfig.outputOracleOwner, deployConfig.l2OutputOracleOwner,
] ]
) )
) )
await tx.wait() await tx.wait()
const submissionInterval = await L2OutputOracle.SUBMISSION_INTERVAL() const submissionInterval = await L2OutputOracle.SUBMISSION_INTERVAL()
if (!submissionInterval.eq(BigNumber.from(deployConfig.submissionInterval))) { if (
!submissionInterval.eq(
BigNumber.from(deployConfig.l2OutputOracleSubmissionInterval)
)
) {
throw new Error('submission internal misconfigured') throw new Error('submission internal misconfigured')
} }
const historicalBlocks = await L2OutputOracle.HISTORICAL_TOTAL_BLOCKS() const historicalBlocks = await L2OutputOracle.HISTORICAL_TOTAL_BLOCKS()
if (!historicalBlocks.eq(BigNumber.from(deployConfig.historicalBlocks))) { if (
!historicalBlocks.eq(
BigNumber.from(deployConfig.l2OutputOracleHistoricalTotalBlocks)
)
) {
throw new Error('historal total blocks misconfigured') throw new Error('historal total blocks misconfigured')
} }
const startingBlockNumber = await L2OutputOracle.STARTING_BLOCK_NUMBER() const startingBlockNumber = await L2OutputOracle.STARTING_BLOCK_NUMBER()
if ( if (
!startingBlockNumber.eq(BigNumber.from(deployConfig.startingBlockNumber)) !startingBlockNumber.eq(
BigNumber.from(deployConfig.l2OutputOracleStartingBlockNumber)
)
) { ) {
throw new Error('starting block number misconfigured') throw new Error('starting block number misconfigured')
} }
const startingTimestamp = await L2OutputOracle.STARTING_TIMESTAMP() const startingTimestamp = await L2OutputOracle.STARTING_TIMESTAMP()
if (!startingTimestamp.eq(BigNumber.from(l1StartingBlock.timestamp))) { if (!startingTimestamp.eq(BigNumber.from(deployL2StartingTimestamp))) {
throw new Error('starting timestamp misconfigured') throw new Error('starting timestamp misconfigured')
} }
const l2BlockTime = await L2OutputOracle.L2_BLOCK_TIME() const l2BlockTime = await L2OutputOracle.L2_BLOCK_TIME()
......
...@@ -35,6 +35,11 @@ const config: HardhatUserConfig = { ...@@ -35,6 +35,11 @@ const config: HardhatUserConfig = {
'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
], ],
}, },
hivenet: {
chainId: Number(process.env.CHAIN_ID),
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
},
goerli: { goerli: {
chainId: 5, chainId: 5,
url: process.env.L1_RPC || '', url: process.env.L1_RPC || '',
...@@ -60,27 +65,272 @@ const config: HardhatUserConfig = { ...@@ -60,27 +65,272 @@ const config: HardhatUserConfig = {
}, },
}, },
deployConfigSpec: { deployConfigSpec: {
submissionInterval: { // To anchor the rollup at for L1 genesis.
// The L2 genesis script uses this to fill the storage of the L1Block info predeploy.
// The rollup config script uses this to fill the L1 genesis info for the rollup.
// The Output oracle deploy script may use it if the L2 starting timestamp is undefined,
// assuming the L2 genesis is set up with this.
l1StartingBlockTag: {
type: 'string',
},
// Required to identify the L1 network and verify and create L1 signatures.
// Part of L1 genesis config.
// "l1_chain_id" in rollup config.
l1ChainID: {
type: 'number',
},
// Required to identify the L2 network and create p2p signatures unique for this chain.
// Part of L2 genesis config.
// "l2_chain_id" in rollup config.
l2ChainID: {
type: 'number', type: 'number',
}, },
// Seconds per L2 block.
//
// The Output oracle deploy script uses this.
//
// "block_time" in rollup config.
l2BlockTime: { l2BlockTime: {
type: 'number', type: 'number',
}, },
genesisOutput: {
// Rollup config parameters. These must ONLY be used by the rollup config script.
// For scripts, use the optimism_rollupConfig RPC method to retrieve the rollup config dynamically.
// -------------------------------------------------
// Sequencer batches may not be more than MaxSequencerDrift seconds after
// the L1 timestamp of the sequencing window end.
//
// Note: When L1 has many 1 second consecutive blocks, and L2 grows at fixed 2 seconds,
// the L2 time may still grow beyond this difference.
//
// "max_sequencer_drift" in rollup config.
maxSequencerDrift: {
type: 'number',
},
// Number of epochs (L1 blocks) per sequencing window.
// "seq_window_size" in rollup config.
sequencerWindowSize: {
type: 'number',
},
// Number of seconds (w.r.t. L1 time) that a frame can be valid when included in L1
// "channel_timeout" in rollup config.
channelTimeout: {
type: 'number',
},
// Address of the key the sequencer uses to sign blocks on the P2P layer
// "p2p_sequencer_address" in rollup config.
p2pSequencerAddress: {
type: 'address',
},
// L2 address used to send all priority fees to, also known as the coinbase address in the block.
// "fee_recipient_address" in rollup config.
optimismL2FeeRecipient: {
type: 'address',
},
// L1 address that batches are sent to.
// "batch_inbox_address" in rollup config.
batchInboxAddress: {
type: 'address',
},
// Acceptable batch-sender address, to filter transactions going into the batchInboxAddress on L1 for data.
// Warning: this address is hardcoded now, but is intended to become governed via L1.
// It may not be part of the rollup config in the near future, and instead be part of a L1 contract deployment.
// "batch_sender_address" in rollup config.
batchSenderAddress: {
type: 'address',
},
// L1 Deposit Contract Address. Not part of the deploy config.
// This is derived from the Portal contract deployment (warning: use proxy address).
// "deposit_contract_address" in the rollup config.
// L2 Output oracle deployment parameters.
// -------------------------------------------------
// uint256 - Interval in blocks at which checkpoints must be submitted.
l2OutputOracleSubmissionInterval: {
type: 'number',
},
// bytes32 - The initial L2 output of the L2 chain.
l2OutputOracleGenesisL2Output: {
type: 'string', type: 'string',
default: ethers.constants.HashZero, default: ethers.constants.HashZero,
}, },
historicalBlocks: { // uint256 - Number of blocks preceding this L2 chain.
l2OutputOracleHistoricalTotalBlocks: {
type: 'number',
default: 0,
},
// uint256 - The number of the first L2 block.
l2OutputOracleStartingBlockNumber: {
type: 'number', type: 'number',
default: 0,
}, },
sequencerAddress: { // Starting time stamp is optional, if it is configured with a negative
// the deploy config user needs to fall back to the timestamp
// of the L1 block that the rollup anchors at (genesis L1).
//
// Note that if you let it fall back to this L1 timestamp, then the L2
// must have a matching timestamp in the block at height l2OutputOracleStartingBlockNumber.
//
// uint256 - The timestamp of the first L2 block.
l2OutputOracleStartingTimestamp: {
type: 'number',
},
// l2OutputOracleL2BlockTime:
// Read from the global l2BlockTime
//
// uint256 - The time per L2 block, in seconds.
// address - The address of the proposer.
l2OutputOracleProposer: {
type: 'address', type: 'address',
}, },
outputOracleOwner: { // address - The address of the owner.
l2OutputOracleOwner: {
type: 'address', type: 'address',
}, },
l1StartingBlockTag: {
// Optional L1 genesis block values. These must ONLY be used by the L1 genesis config script.
// Not all deployments may create a new L1 chain, but instead attach to an existing L1 chain, like Goerli.
// -------------------------------------------------
l1BlockTime: {
type: 'number',
default: 15,
},
l1GenesisBlockNonce: {
type: 'string', // uint64
default: '0x0',
},
// l1GenesisBlockTimestamp: not part of deploy config, configured with parameter to genesis task instead.
// l1GenesisBlockExtraData: not configurable, used for clique singer data. See cliqueSignerAddress instead.
cliqueSignerAddress: {
type: 'address',
default: ethers.constants.AddressZero,
},
l1GenesisBlockGasLimit: {
type: 'string', type: 'string',
default: ethers.BigNumber.from(15_000_000).toHexString(),
},
l1GenesisBlockDifficulty: {
type: 'string', // uint256
default: '0x1',
},
l1GenesisBlockMixHash: {
type: 'string', // bytes32
default: ethers.constants.HashZero,
},
l1GenesisBlockCoinbase: {
type: 'address',
default: ethers.constants.AddressZero,
},
// l1GenesisBlockAlloc: the storage tree is not configurable with deploy-config.
l1GenesisBlockNumber: {
type: 'string', // uint64
default: '0x0',
},
l1GenesisBlockGasUsed: {
type: 'string', // uint64
default: '0x0',
},
l1GenesisBlockParentHash: {
type: 'string', // bytes32
default: ethers.constants.HashZero,
},
l1GenesisBlockBaseFeePerGas: {
type: 'string', // uint256
default: ethers.BigNumber.from(1000_000_000).toHexString(), // 1 gwei
},
// Optional L2 genesis block values. These must ONLY be used by the L2 genesis config script.
// -------------------------------------------------
l2GenesisBlockNonce: {
type: 'string', // uint64
default: '0x0',
},
// l2GenesisBlockTimestamp: configured dynamically, based on the timestamp of l1StartingBlockTag.
l2GenesisBlockExtraData: {
type: 'string', // important: in the case of L2, which uses post-Merge Ethereum rules, this must be <= 32 bytes.
default: ethers.constants.HashZero,
},
l2GenesisBlockGasLimit: {
type: 'string',
default: ethers.BigNumber.from(15_000_000).toHexString(),
},
l2GenesisBlockDifficulty: {
type: 'string', // uint256
default: '0x1',
},
l2GenesisBlockMixHash: {
type: 'string', // bytes32
default: ethers.constants.HashZero,
},
l2GenesisBlockCoinbase: {
type: 'address',
default: ethers.constants.AddressZero,
},
// l2GenesisBlockAlloc: the storage tree is not configurable with deploy-config.
l2GenesisBlockNumber: {
type: 'string', // uint64
default: '0x0',
},
l2GenesisBlockGasUsed: {
type: 'string', // uint64
default: '0x0',
},
l2GenesisBlockParentHash: {
type: 'string', // bytes32
default: ethers.constants.HashZero,
},
l2GenesisBlockBaseFeePerGas: {
type: 'string', // uint256
default: ethers.BigNumber.from(1000_000_000).toHexString(), // 1 gwei
},
// L2 chain configuration values
optimismBaseFeeRecipient: {
type: 'address',
default: ethers.constants.AddressZero,
},
optimismL1FeeRecipient: {
type: 'address',
default: ethers.constants.AddressZero,
},
// L2 predeploy variables
l2CrossDomainMessengerOwner: {
type: 'address',
default: ethers.constants.AddressZero,
},
gasPriceOracleOwner: {
type: 'address',
default: ethers.constants.AddressZero,
},
gasPriceOracleOverhead: {
type: 'number',
default: 2100,
},
gasPriceOracleScalar: {
type: 'number',
default: 1000_000,
},
gasPriceOracleDecimals: {
type: 'number',
default: 6,
},
proxyAdmin: {
type: 'address',
// no default, important to get right.
},
fundDevAccounts: {
type: 'boolean',
default: false,
},
deploymentWaitConfirmations: {
type: 'number',
default: 1,
}, },
}, },
external: { external: {
......
import fs from 'fs' import fs from 'fs'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { task } from 'hardhat/config' import { task, types } from 'hardhat/config'
import { Genesis, State } from '@eth-optimism/core-utils' import { Genesis, State } from '@eth-optimism/core-utils'
import '@eth-optimism/hardhat-deploy-config' import '@eth-optimism/hardhat-deploy-config'
...@@ -11,10 +11,21 @@ task('genesis-l1', 'create a genesis config') ...@@ -11,10 +11,21 @@ task('genesis-l1', 'create a genesis config')
'The file to write the output JSON to', 'The file to write the output JSON to',
'genesis.json' 'genesis.json'
) )
.addOptionalParam(
'l1GenesisBlockTimestamp',
'Timestamp to embed in L1 genesis block, current time will be used if the timestamp is zero',
0,
types.int
)
.setAction(async (args, hre) => { .setAction(async (args, hre) => {
const { deployConfig } = hre const { deployConfig } = hre
const alloc: State = {} const alloc: State = {}
const l1GenesisBlockTimestamp =
args.l1GenesisBlockTimestamp === 0
? Math.floor(Date.now() / 1000)
: args.l1GenesisBlockTimestamp
// Give each predeploy a single wei // Give each predeploy a single wei
for (let i = 0; i <= 0xff; i++) { for (let i = 0; i <= 0xff; i++) {
const buf = Buffer.alloc(2) const buf = Buffer.alloc(2)
...@@ -61,18 +72,12 @@ task('genesis-l1', 'create a genesis config') ...@@ -61,18 +72,12 @@ task('genesis-l1', 'create a genesis config')
} }
} }
const timestamp = hre.deployConfig.l1GenesisTimestamp
if (timestamp === undefined) {
throw new Error('Must configure starting block timestamp')
}
const genesis: Genesis = { const genesis: Genesis = {
config: { config: {
chainId: 900, chainId: deployConfig.l1ChainID,
homesteadBlock: 0, homesteadBlock: 0,
eip150Block: 0, eip150Block: 0,
eip150Hash: eip150Hash: ethers.constants.HashZero,
'0x0000000000000000000000000000000000000000000000000000000000000000',
eip155Block: 0, eip155Block: 0,
eip158Block: 0, eip158Block: 0,
byzantiumBlock: 0, byzantiumBlock: 0,
...@@ -83,20 +88,26 @@ task('genesis-l1', 'create a genesis config') ...@@ -83,20 +88,26 @@ task('genesis-l1', 'create a genesis config')
berlinBlock: 0, berlinBlock: 0,
londonBlock: 0, londonBlock: 0,
clique: { clique: {
period: 15, period: deployConfig.l1BlockTime,
epoch: 30000, epoch: 30000,
}, },
}, },
nonce: '0x0', nonce: deployConfig.l1GenesisBlockNonce,
timestamp: ethers.BigNumber.from(timestamp).toHexString(), timestamp: ethers.BigNumber.from(l1GenesisBlockTimestamp).toHexString(),
extraData: extraData: ethers.utils.hexConcat([
'0x0000000000000000000000000000000000000000000000000000000000000000ca062b0fd91172d89bcd4bb084ac4e21972cc4670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', ethers.constants.HashZero,
gasLimit: ethers.BigNumber.from(15_000_000).toHexString(), deployConfig.cliqueSignerAddress,
difficulty: '0x1', ethers.utils.hexZeroPad('0x', 65),
mixHash: ]),
'0x0000000000000000000000000000000000000000000000000000000000000000', gasLimit: deployConfig.l1GenesisBlockGasLimit,
coinbase: '0x0000000000000000000000000000000000000000', difficulty: deployConfig.l1GenesisBlockDifficulty,
mixHash: deployConfig.l1GenesisBlockMixHash,
coinbase: deployConfig.l1GenesisBlockCoinbase,
alloc, alloc,
number: deployConfig.l1GenesisBlockNumber,
gasUsed: deployConfig.l1GenesisBlockGasUsed,
parentHash: deployConfig.l1GenesisBlockParentHash,
baseFeePerGas: deployConfig.l1GenesisBlockBaseFeePerGas,
} }
fs.writeFileSync(args.outfile, JSON.stringify(genesis, null, 2)) fs.writeFileSync(args.outfile, JSON.stringify(genesis, null, 2))
......
...@@ -210,6 +210,17 @@ task('genesis-l2', 'create a genesis config') ...@@ -210,6 +210,17 @@ task('genesis-l2', 'create a genesis config')
const l1 = new ethers.providers.StaticJsonRpcProvider(args.l1RpcUrl) const l1 = new ethers.providers.StaticJsonRpcProvider(args.l1RpcUrl)
const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag)
if (l1StartingBlock === null) {
throw new Error(
`Cannot fetch block tag ${deployConfig.l1StartingBlockTag}`
)
}
if (l1StartingBlock === null) {
console.log(`Unable to fetch L1 block that rollup starts at`)
}
// Use the addresses of the proxies here instead of the implementations // Use the addresses of the proxies here instead of the implementations
// Be backwards compatible // Be backwards compatible
let ProxyL1CrossDomainMessenger = await hre.deployments.getOrNull( let ProxyL1CrossDomainMessenger = await hre.deployments.getOrNull(
...@@ -255,11 +266,11 @@ task('genesis-l2', 'create a genesis config') ...@@ -255,11 +266,11 @@ task('genesis-l2', 'create a genesis config')
l1FeeWallet: ethers.constants.AddressZero, l1FeeWallet: ethers.constants.AddressZero,
}, },
L1Block: { L1Block: {
number: deployConfig.l1BlockInitialNumber, number: l1StartingBlock.number,
timestamp: deployConfig.l1BlockInitialTimestamp, timestamp: l1StartingBlock.timestamp,
basefee: deployConfig.l1BlockInitialBasefee, basefee: l1StartingBlock.baseFeePerGas,
hash: deployConfig.l1BlockInitialHash, hash: l1StartingBlock.hash,
sequenceNumber: deployConfig.l1BlockInitialSequenceNumber, sequenceNumber: 0,
}, },
LegacyERC20ETH: { LegacyERC20ETH: {
bridge: predeploys.L2StandardBridge, bridge: predeploys.L2StandardBridge,
...@@ -462,24 +473,14 @@ task('genesis-l2', 'create a genesis config') ...@@ -462,24 +473,14 @@ task('genesis-l2', 'create a genesis config')
} }
} }
const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag)
if (l1StartingBlock === null) {
throw new Error(
`Cannot fetch block tag ${deployConfig.l1StartingBlockTag}`
)
}
if (l1StartingBlock === null) {
console.log(`Unable to fetch L1 starting timestamp`)
}
const startingTimestamp = l1StartingBlock?.timestamp || 0 const startingTimestamp = l1StartingBlock?.timestamp || 0
const genesis: OptimismGenesis = { const genesis: OptimismGenesis = {
config: { config: {
chainId: deployConfig.genesisBlockChainid, chainId: deployConfig.l2ChainID,
homesteadBlock: 0, homesteadBlock: 0,
eip150Block: 0, eip150Block: 0,
eip150Hash: ethers.constants.HashZero,
eip155Block: 0, eip155Block: 0,
eip158Block: 0, eip158Block: 0,
byzantiumBlock: 0, byzantiumBlock: 0,
...@@ -496,11 +497,17 @@ task('genesis-l2', 'create a genesis config') ...@@ -496,11 +497,17 @@ task('genesis-l2', 'create a genesis config')
l1FeeRecipient: deployConfig.optimismL1FeeRecipient, l1FeeRecipient: deployConfig.optimismL1FeeRecipient,
}, },
}, },
nonce: '0x1234', nonce: deployConfig.l2GenesisBlockNonce,
difficulty: '0x1',
timestamp: ethers.BigNumber.from(startingTimestamp).toHexString(), timestamp: ethers.BigNumber.from(startingTimestamp).toHexString(),
gasLimit: deployConfig.genesisBlockGasLimit, extraData: deployConfig.l2GenesisBlockExtraData,
extraData: deployConfig.genesisBlockExtradata, gasLimit: deployConfig.l2GenesisBlockGasLimit,
difficulty: deployConfig.l2GenesisBlockDifficulty,
mixHash: deployConfig.l2GenesisBlockMixHash,
coinbase: deployConfig.l2GenesisBlockCoinbase,
number: deployConfig.l2GenesisBlockNumber,
gasUsed: deployConfig.l2GenesisBlockGasUsed,
parentHash: deployConfig.l2GenesisBlockParentHash,
baseFeePerGas: deployConfig.l2GenesisBlockBaseFeePerGas,
alloc, alloc,
} }
......
...@@ -7,13 +7,13 @@ task('rekey', 'Generates a new set of keys for a test network').setAction( ...@@ -7,13 +7,13 @@ task('rekey', 'Generates a new set of keys for a test network').setAction(
const mnemonic = bip39.generateMnemonic() const mnemonic = bip39.generateMnemonic()
const pathPrefix = "m/44'/60'/0'/0" const pathPrefix = "m/44'/60'/0'/0"
const labels = [ const labels = [
'sequencerAddress', 'l2OutputOracleProposer',
'proxyAdmin', 'proxyAdmin',
'optimismBaseFeeRecipient', 'optimismBaseFeeRecipient',
'optimismL1FeeRecipient', 'optimismL1FeeRecipient',
'optimismL2FeeRecipient', 'optimismL2FeeRecipient',
'p2pSequencerAddress', 'p2pSequencerAddress',
'outputOracleOwner', 'l2OutputOracleOwner',
'batchSenderAddress', 'batchSenderAddress',
] ]
......
...@@ -20,7 +20,21 @@ task('rollup-config', 'create a genesis config') ...@@ -20,7 +20,21 @@ task('rollup-config', 'create a genesis config')
const l1 = new ethers.providers.StaticJsonRpcProvider(args.l1RpcUrl) const l1 = new ethers.providers.StaticJsonRpcProvider(args.l1RpcUrl)
const l2 = new ethers.providers.StaticJsonRpcProvider(args.l2RpcUrl) const l2 = new ethers.providers.StaticJsonRpcProvider(args.l2RpcUrl)
const l2Genesis = await l2.getBlock('earliest') // sanity check our RPC connections
const l1ChainID = await getChainId(l1)
if (l1ChainID !== deployConfig.l1ChainID) {
throw new Error(
`connected to L1 RPC ${args.l1RpcUrl} yielded chain ID ${l1ChainID} but expected ${deployConfig.l1ChainID}`
)
}
const l2ChainID = await getChainId(l2)
if (l2ChainID !== deployConfig.l2ChainID) {
throw new Error(
`connected to L2 RPC ${args.l2RpcUrl} yielded chain ID ${l2ChainID} but expected ${deployConfig.l2ChainID}`
)
}
const l2GenesisBlock = await l2.getBlock('earliest')
const portal = await hre.deployments.get('OptimismPortalProxy') const portal = await hre.deployments.get('OptimismPortalProxy')
const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag) const l1StartingBlock = await l1.getBlock(deployConfig.l1StartingBlockTag)
...@@ -37,8 +51,8 @@ task('rollup-config', 'create a genesis config') ...@@ -37,8 +51,8 @@ task('rollup-config', 'create a genesis config')
number: l1StartingBlock.number, number: l1StartingBlock.number,
}, },
l2: { l2: {
hash: l2Genesis.hash, hash: l2GenesisBlock.hash,
number: 0, number: l2GenesisBlock.number,
}, },
l2_time: l1StartingBlock.timestamp, l2_time: l1StartingBlock.timestamp,
}, },
...@@ -47,12 +61,12 @@ task('rollup-config', 'create a genesis config') ...@@ -47,12 +61,12 @@ task('rollup-config', 'create a genesis config')
seq_window_size: deployConfig.sequencerWindowSize, seq_window_size: deployConfig.sequencerWindowSize,
channel_timeout: deployConfig.channelTimeout, channel_timeout: deployConfig.channelTimeout,
l1_chain_id: await getChainId(l1), l1_chain_id: deployConfig.l1ChainID,
l2_chain_id: await getChainId(l2), l2_chain_id: deployConfig.l2ChainID,
p2p_sequencer_address: deployConfig.p2pSequencerAddress, p2p_sequencer_address: deployConfig.p2pSequencerAddress,
fee_recipient_address: deployConfig.optimismL2FeeRecipient, fee_recipient_address: deployConfig.optimismL2FeeRecipient,
batch_inbox_address: '0xff00000000000000000000000000000000000002', batch_inbox_address: deployConfig.batchInboxAddress,
batch_sender_address: deployConfig.batchSenderAddress, batch_sender_address: deployConfig.batchSenderAddress,
deposit_contract_address: portal.address, deposit_contract_address: portal.address,
} }
......
...@@ -60,6 +60,7 @@ export interface Genesis { ...@@ -60,6 +60,7 @@ export interface Genesis {
gasUsed?: string gasUsed?: string
parentHash?: string parentHash?: string
extraData: string extraData: string
baseFeePerGas?: string
alloc: State alloc: State
} }
......
import { HardhatUserConfig } from 'hardhat/types' import { HardhatUserConfig } from 'hardhat/types'
import { ethers } from 'ethers'
import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-ethers'
import '@nomiclabs/hardhat-waffle' import '@nomiclabs/hardhat-waffle'
...@@ -20,6 +21,10 @@ const config: HardhatUserConfig = { ...@@ -20,6 +21,10 @@ const config: HardhatUserConfig = {
'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
], ],
}, },
hivenet: {
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
},
}, },
external: { external: {
contracts: [ contracts: [
...@@ -28,6 +33,7 @@ const config: HardhatUserConfig = { ...@@ -28,6 +33,7 @@ const config: HardhatUserConfig = {
}, },
], ],
deployments: { deployments: {
hivenet: ['../contracts-bedrock/deployments/hivenet'],
devnetL1: ['../contracts-bedrock/deployments/devnetL1'], devnetL1: ['../contracts-bedrock/deployments/devnetL1'],
goerli: ['../contracts-bedrock/deployments/goerli'], goerli: ['../contracts-bedrock/deployments/goerli'],
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment