deploy-token.ts 6.56 KB
Newer Older
1 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
import { task, types } from 'hardhat/config'
import { ethers } from 'ethers'
import { LedgerSigner } from '@ethersproject/hardware-wallets'
import dotenv from 'dotenv'

import { prompt } from '../src/prompt'
dotenv.config()

// Hardcode the expected addresse
const addresses = {
  governanceToken: '0x4200000000000000000000000000000000000042',
}

task('deploy-token', 'Deploy governance token and its mint manager contracts')
  .addParam('mintManagerOwner', 'Owner of the mint manager')
  .addOptionalParam('useLedger', 'User ledger hardware wallet as signer')
  .addOptionalParam(
    'ledgerTokenDeployerPath',
    'Ledger key derivation path for the token deployer account',
    ethers.utils.defaultPath,
    types.string
  )
  .addParam(
    'pkDeployer',
    'Private key for main deployer account',
    process.env.PRIVATE_KEY_DEPLOYER
  )
  .addOptionalParam(
    'pkTokenDeployer',
    'Private key for the token deployer account',
    process.env.PRIVATE_KEY_TOKEN_DEPLOYER
  )
  .setAction(async (args, hre) => {
    console.log('Deploying token to', hre.network.name, 'network')
    // There cannot be two ledgers at the same time
    let tokenDeployer
    // Deploy the token
    if (args.useLedger) {
      // Token is deployed to a system address at `0x4200000000000000000000000000000000000042`
      // For that a dedicated deployer account is used
      tokenDeployer = new LedgerSigner(
        hre.ethers.provider,
        'default',
        args.ledgerTokenDeployerPath
      )
    } else {
      tokenDeployer = new hre.ethers.Wallet(args.pkTokenDeployer).connect(
        hre.ethers.provider
      )
    }

    // Create the MintManager Deployer
    const deployer = new hre.ethers.Wallet(args.pkDeployer).connect(
      hre.ethers.provider
    )

    // Get the sizes of the bytecode to check if the contracts
    // have already been deployed. Useful for an error partway through
    // the script
    const governanceTokenCode = await hre.ethers.provider.getCode(
      addresses.governanceToken
    )

    const addrTokenDeployer = await tokenDeployer.getAddress()
    console.log(`Using token deployer: ${addrTokenDeployer}`)

    const tokenDeployerBalance = await tokenDeployer.getBalance()
    if (tokenDeployerBalance.eq(0)) {
      throw new Error(`Token deployer has no balance`)
    }
    console.log(`Token deployer balance: ${tokenDeployerBalance.toString()}`)
    const nonceTokenDeployer = await tokenDeployer.getTransactionCount()
    console.log(`Token deployer nonce: ${nonceTokenDeployer}`)

    const GovernanceToken = await hre.ethers.getContractFactory(
      'GovernanceToken'
    )
    let governanceToken = GovernanceToken.attach(
      addresses.governanceToken
    ).connect(tokenDeployer)

    if (nonceTokenDeployer === 0 && governanceTokenCode === '0x') {
      await prompt('Ready to deploy. Does everything look OK?')
      // Deploy the GovernanceToken
      governanceToken = await GovernanceToken.connect(tokenDeployer).deploy()
      const tokenReceipt = await governanceToken.deployTransaction.wait()
      console.log('GovernanceToken deployed to:', tokenReceipt.contractAddress)

      if (tokenReceipt.contractAddress !== addresses.governanceToken) {
        console.log(
          `Expected governance token address ${addresses.governanceToken}`
        )
        console.log(`Got ${tokenReceipt.contractAddress}`)
        throw new Error(`Fatal error! Mismatch of governance token address`)
      }
96 97 98 99
    } else if (nonceTokenDeployer !== 0 && governanceTokenCode === '0x') {
      throw new Error(
        `Nonce is ${nonceTokenDeployer} without governance token deployed`
      )
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
    } else {
      console.log(
        `GovernanceToken already deployed at ${addresses.governanceToken}, skipping`
      )
      console.log(`Deployer nonce: ${nonceTokenDeployer}`)
      console.log(`Code size: ${governanceTokenCode.length}`)
    }

    const { mintManagerOwner } = args

    // Do the deployer things
    console.log('Deploying MintManager')
    const addr = await deployer.getAddress()
    console.log(`Using MintManager deployer: ${addr}`)

    const deployerBalance = await deployer.getBalance()
    if (deployerBalance.eq(0)) {
      throw new Error('Deployer has no balance')
    }
    console.log(`Deployer balance: ${deployerBalance.toString()}`)
    const deployerNonce = await deployer.getTransactionCount()
    console.log(`Deployer nonce: ${deployerNonce}`)
    await prompt('Does this look OK?')

    const MintManager = await hre.ethers.getContractFactory('MintManager')
    // Deploy the MintManager
    console.log(
      `Deploying MintManager with (${mintManagerOwner}, ${addresses.governanceToken})`
    )
    const mintManager = await MintManager.connect(deployer).deploy(
      mintManagerOwner,
      addresses.governanceToken
    )

    const receipt = await mintManager.deployTransaction.wait()
    console.log(`Deployed mint manager to ${receipt.contractAddress}`)
    let mmOwner = await mintManager.owner()
    const currTokenOwner = await governanceToken
      .attach(addresses.governanceToken)
      .owner()
    console.log(
      'About to transfer ownership of the token to the mint manager! This is irreversible.'
    )
    console.log(`Current token owner:   ${currTokenOwner}`)
    console.log(`Mint manager address:  ${mintManager.address}`)
    console.log(`Mint manager owner:    ${mmOwner}`)
    await prompt('Is this OK?')

    console.log('Transferring ownership...')
    // Transfer ownership of the token to the MintManager instance
    const tx = await governanceToken
      .attach(addresses.governanceToken)
      .transferOwnership(mintManager.address)
    await tx.wait()
    console.log(
      `Transferred ownership of governance token to ${mintManager.address}`
    )

    console.log('MintManager deployed to:', receipt.contractAddress)
    console.log('MintManager owner set to:', mintManagerOwner)
    console.log(
      'MintManager governanceToken set to:',
      addresses.governanceToken
    )
    console.log('### Token deployment complete ###')

    const tokOwner = await governanceToken
      .attach(addresses.governanceToken)
      .owner()
    if (tokOwner !== mintManager.address) {
      throw new Error(`GovernanceToken owner not set correctly`)
    }

    // Check that the deployment went as expected
    const govToken = await mintManager.governanceToken()
    if (govToken !== addresses.governanceToken) {
      throw new Error(`MintManager governance token not set correctly`)
    }
    mmOwner = await mintManager.owner()
    if (mmOwner !== mintManagerOwner) {
      throw new Error(`MintManager owner not set correctly`)
    }
    console.log('Validated MintManager config')
  })