validation-utils.ts 2.99 KB
Newer Older
1
import { createInterface } from 'readline'
2

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
import { hexStringEquals } from '@eth-optimism/core-utils'

export const getInput = (query) => {
  const rl = createInterface({
    input: process.stdin,
    output: process.stdout,
  })

  return new Promise((resolve) =>
    rl.question(query, (ans) => {
      rl.close()
      resolve(ans)
    })
  )
}

const codes = {
  reset: '\x1b[0m',
  red: '\x1b[0;31m',
  green: '\x1b[0;32m',
  cyan: '\x1b[0;36m',
  yellow: '\x1b[1;33m',
}

export const color = Object.fromEntries(
  Object.entries(codes).map(([k]) => [
    k,
    (msg: string) => `${codes[k]}${msg}${codes.reset}`,
  ])
)

34 35 36
// helper for finding the right artifact from the deployed name
const locateArtifact = (name: string) => {
  return {
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    'ChainStorageContainer-CTC-batches':
      'L1/rollup/ChainStorageContainer.sol/ChainStorageContainer.json',
    'ChainStorageContainer-SCC-batches':
      'L1/rollup/ChainStorageContainer.sol/ChainStorageContainer.json',
    CanonicalTransactionChain:
      'L1/rollup/CanonicalTransactionChain.sol/CanonicalTransactionChain.json',
    StateCommitmentChain:
      'L1/rollup/StateCommitmentChain.sol/StateCommitmentChain.json',
    BondManager: 'L1/verification/BondManager.sol/BondManager.json',
    OVM_L1CrossDomainMessenger:
      'L1/messaging/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json',
    Proxy__OVM_L1CrossDomainMessenger:
      'libraries/resolver/Lib_ResolvedDelegateProxy.sol/Lib_ResolvedDelegateProxy.json',
    Proxy__OVM_L1StandardBridge:
      'chugsplash/L1ChugSplashProxy.sol/L1ChugSplashProxy.json',
52 53 54 55
  }[name]
}

export const getArtifactFromManagedName = (name: string) => {
56
  // eslint-disable-next-line @typescript-eslint/no-var-requires
57
  return require(`../artifacts/contracts/${locateArtifact(name)}`)
58 59 60 61 62 63 64 65 66 67 68 69
}

export const getEtherscanUrl = (network, address: string) => {
  const escPrefix = network.chainId !== 1 ? `${network.name}.` : ''
  return `https://${escPrefix}etherscan.io/address/${address}`
}

// Reduces a byte string to first 32 bytes, with a '...' to indicate when it was shortened
const truncateLongString = (value: string): string => {
  return value.length > 66 ? `${value.slice(0, 66)}...` : value
}

70 71 72 73 74 75 76
export const printSectionHead = (msg: string) => {
  console.log(color.cyan(msg))
  console.log(
    color.cyan('='.repeat(Math.max(...msg.split('\n').map((s) => s.length))))
  )
}

77 78 79
export const printComparison = (
  action: string,
  description: string,
80 81
  expected: { name: string; value: any },
  deployed: { name: string; value: any }
82
) => {
83
  console.log(`\n${action}:`)
84 85
  if (hexStringEquals(expected.value, deployed.value)) {
    console.log(
86 87 88 89 90
      color.green(`${expected.name}: ${truncateLongString(expected.value)}`)
    )
    console.log('matches')
    console.log(
      color.green(`${deployed.name}: ${truncateLongString(deployed.value)}`)
91 92 93
    )
    console.log(color.green(`${description} looks good! 😎`))
  } else {
94 95 96
    throw new Error(
      `${description} looks wrong. ${expected.value}\ndoes not match\n${deployed.value}.`
    )
97 98
  }
}