take-dump.ts 5.5 KB
Newer Older
1 2
import * as path from 'path'
import * as fs from 'fs'
3
import { exec } from 'child_process'
4 5
import { promisify } from 'util'

6
import * as mkdirp from 'mkdirp'
7
import { ethers } from 'ethers'
8
import { task } from 'hardhat/config'
9
import { remove0x } from '@eth-optimism/core-utils'
10
import '@eth-optimism/hardhat-deploy-config'
11

12 13 14 15
import { predeploys } from '../src/predeploys'
import { getContractFromArtifact } from '../src/deploy-utils'
import { names } from '../src/address-names'

16
task('take-dump').setAction(async ({}, hre) => {
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
  /* eslint-disable @typescript-eslint/no-var-requires */

  // Needs to be imported here or hardhat will throw a fit about hardhat being imported from
  // within the configuration file.
  const {
    computeStorageSlots,
    getStorageLayout,
  } = require('@defi-wonderland/smock/dist/src/utils')

  // Needs to be imported here because the artifacts can only be generated after the contracts have
  // been compiled, but compiling the contracts will import the config file which, as a result,
  // will import this file.
  const { getContractArtifact } = require('../src/contract-artifacts')

  /* eslint-enable @typescript-eslint/no-var-requires */

  // Basic warning so users know that the whitelist will be disabled if the owner is the zero address.
  if (
35 36
    hre.deployConfig.ovmWhitelistOwner === undefined ||
    hre.deployConfig.ovmWhitelistOwner === ethers.constants.AddressZero
37 38 39 40
  ) {
    console.log(
      'WARNING: whitelist owner is undefined or address(0), whitelist will be disabled'
    )
41 42
  }

43 44
  const variables = {
    OVM_DeployerWhitelist: {
45
      owner: hre.deployConfig.ovmWhitelistOwner,
46 47
    },
    OVM_GasPriceOracle: {
48 49 50 51 52 53
      _owner: hre.deployConfig.ovmGasPriceOracleOwner,
      gasPrice: hre.deployConfig.gasPriceOracleL2GasPrice,
      l1BaseFee: hre.deployConfig.gasPriceOracleL1BaseFee,
      overhead: hre.deployConfig.gasPriceOracleOverhead,
      scalar: hre.deployConfig.gasPriceOracleScalar,
      decimals: hre.deployConfig.gasPriceOracleDecimals,
54
    },
55
    L2StandardBridge: {
56 57 58 59 60 61
      l1TokenBridge: (
        await getContractFromArtifact(
          hre,
          names.managed.contracts.Proxy__OVM_L1StandardBridge
        )
      ).address,
62
      messenger: predeploys.L2CrossDomainMessenger,
63 64
    },
    OVM_SequencerFeeVault: {
65
      l1FeeWallet: hre.deployConfig.ovmFeeWalletAddress,
66 67
    },
    OVM_ETH: {
68
      l2Bridge: predeploys.L2StandardBridge,
69
      l1Token: ethers.constants.AddressZero,
70 71 72
      _name: 'Ether',
      _symbol: 'ETH',
    },
73
    L2CrossDomainMessenger: {
74 75 76
      // We default the xDomainMsgSender to this value to save gas.
      // See usage of this default in the L2CrossDomainMessenger contract.
      xDomainMsgSender: '0x000000000000000000000000000000000000dEaD',
77 78 79 80 81 82
      l1CrossDomainMessenger: (
        await getContractFromArtifact(
          hre,
          names.managed.contracts.Proxy__OVM_L1CrossDomainMessenger
        )
      ).address,
83 84
      // Set the messageNonce to a high value to avoid overwriting old sent messages.
      messageNonce: 100000,
85
    },
86 87 88 89 90
    WETH9: {
      name: 'Wrapped Ether',
      symbol: 'WETH',
      decimals: 18,
    },
91 92 93 94 95 96 97 98 99 100
  }

  const dump = {}
  for (const predeployName of Object.keys(predeploys)) {
    const predeployAddress = predeploys[predeployName]
    dump[predeployAddress] = {
      balance: '00',
      storage: {},
    }

101 102 103 104
    if (predeployName === 'OVM_L1BlockNumber') {
      // OVM_L1BlockNumber is a special case where we just inject a specific bytecode string.
      // We do this because it uses the custom L1BLOCKNUMBER opcode (0x4B) which cannot be
      // directly used in Solidity (yet). This bytecode string simply executes the 0x4B opcode
105
      // and returns the address given by that opcode.
kf's avatar
kf committed
106
      dump[predeployAddress].code = '0x4B60005260206000F3'
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
    } else {
      const artifact = getContractArtifact(predeployName)
      dump[predeployAddress].code = artifact.deployedBytecode
    }

    // Compute and set the required storage slots for each contract that needs it.
    if (predeployName in variables) {
      const storageLayout = await getStorageLayout(predeployName)
      const slots = computeStorageSlots(storageLayout, variables[predeployName])
      for (const slot of slots) {
        dump[predeployAddress].storage[slot.key] = slot.val
      }
    }
  }

122 123 124 125 126 127 128 129 130 131
  // Grab the commit hash so we can stick it in the genesis file.
  let commit: string
  try {
    const { stdout } = await promisify(exec)('git rev-parse HEAD')
    commit = stdout.replace('\n', '')
  } catch {
    console.log('unable to get commit hash, using empty hash instead')
    commit = '0000000000000000000000000000000000000000'
  }

132
  const genesis = {
133
    commit,
134
    config: {
135
      chainId: hre.deployConfig.l2ChainId,
136 137 138 139 140 141 142 143 144
      homesteadBlock: 0,
      eip150Block: 0,
      eip155Block: 0,
      eip158Block: 0,
      byzantiumBlock: 0,
      constantinopleBlock: 0,
      petersburgBlock: 0,
      istanbulBlock: 0,
      muirGlacierBlock: 0,
145
      berlinBlock: hre.deployConfig.hfBerlinBlock,
146 147 148 149 150 151
      clique: {
        period: 0,
        epoch: 30000,
      },
    },
    difficulty: '1',
152
    gasLimit: hre.deployConfig.l2BlockGasLimit.toString(10),
153 154 155
    extradata:
      '0x' +
      '00'.repeat(32) +
156
      remove0x(hre.deployConfig.ovmBlockSignerAddress) +
157 158 159
      '00'.repeat(65),
    alloc: dump,
  }
160 161 162 163 164 165 166 167 168

  // Make sure the output location exists
  const outdir = path.resolve(__dirname, '../genesis')
  const outfile = path.join(outdir, `${hre.network.name}.json`)
  mkdirp.sync(outdir)

  // Write the genesis file
  fs.writeFileSync(outfile, JSON.stringify(genesis, null, 4))
})