2022-12-09 18:15:16 +08:00

284 lines
7.3 KiB
TypeScript

require('dotenv').config()
import prompt from 'prompt'
import { BigNumber } from 'ethers'
import {
readConfigFile,
updateConfigFile,
execScript,
getNetworkDataByNetworkName,
getTokenSymbolLetterCase,
Logger
} from '../shared/utils'
import { ZERO_ADDRESS } from '../../config/constants'
import { NetworkData } from '../../config/networks/index'
const logger = Logger('deploy')
async function main () {
logger.log('deploy script initiated')
let l1NetworkName: string
let l2NetworkName: string
let tokenSymbol: string
let bonderAddress: string
let isL1BridgeDeploy: boolean
let l2CanonicalTokenIsEth: boolean
let deploymentStep: number
;({
l1NetworkName,
l2NetworkName,
tokenSymbol,
bonderAddress,
isL1BridgeDeploy,
l2CanonicalTokenIsEth,
deploymentStep
} = await getPrompts())
validateInput(l1NetworkName, l2NetworkName, tokenSymbol, bonderAddress)
const basePath: string = 'scripts/deployAndSetupHop'
const scripts: string[] = []
if (isL1BridgeDeploy) {
setL1BridgeNetworkParams(l1NetworkName, l2NetworkName, tokenSymbol, bonderAddress)
scripts.push(`hardhat run ${basePath}/deployL1.ts --network ${l1NetworkName}`)
}
setNetworkParams(l1NetworkName, l2NetworkName, tokenSymbol, bonderAddress, l2CanonicalTokenIsEth)
/**
* 注意发布顺序,如果是本地测试,发布顺序为:
* 1.erc20 deploy
* 2.deployL1
* 3.deployL2
*/
l2NetworkName = handleCustomL2NetworkName(l1NetworkName, l2NetworkName)
const deployL2Cmd = `hardhat run ${basePath}/deployL2.ts --network ${l2NetworkName}`
const setupL1Cmd = `hardhat run ${basePath}/setupL1.ts --network ${l1NetworkName}`
const setupL2Cmd = `hardhat run ${basePath}/setupL2.ts --network ${l2NetworkName}`
if (deploymentStep === 0) {
scripts.push(
deployL2Cmd,
setupL1Cmd,
setupL2Cmd
)
} else if (deploymentStep === 1) {
scripts.push(deployL2Cmd)
} else if (deploymentStep === 2) {
scripts.push(setupL1Cmd)
} else if (deploymentStep === 3) {
scripts.push(setupL2Cmd)
}
for (let i = 0; i < scripts.length; i++) {
const script = scripts[i]
logger.log(`executing script ${i + 1}/${scripts.length} "${script}"`)
await execScript(script)
}
logger.log('complete')
}
async function getPrompts () {
prompt.start()
prompt.message = ''
prompt.delimiter = ''
const res = await prompt.get([{
name: 'l1NetworkName',
description: 'L1 Network Name:',
type: 'string',
required: true,
}, {
name: 'l2NetworkName',
description: 'L2 Network Name:',
type: 'string',
required: true
}, {
name: 'tokenSymbol',
description: 'Token Symbol:',
type: 'string',
required: true
}, {
name: 'bonderAddress',
description: 'Bonder Address:',
type: 'string',
required: true,
default: ZERO_ADDRESS
}, {
name: 'isL1BridgeDeploy',
description: 'Is this an L1 Bridge Deployment:',
type: 'boolean',
required: true,
default: false
}, {
name: 'l2CanonicalTokenIsEth',
description: 'Is the l2 canonical token a native asset',
type: 'boolean',
required: true,
default: false
}, {
name: 'deploymentStep',
description: 'Deployment Step (0 for all) (0, 1, 2, or 3)',
type: 'number',
required: true,
default: 0
}, {
name: 'didSendBridgeFunds',
description: 'Did you send funds over the native bridge for LP AND convert to wrapped if needed?',
type: 'boolean',
required: true,
default: true
}])
const l1NetworkName: string = (res.l1NetworkName as string).toLowerCase()
const l2NetworkName: string = (res.l2NetworkName as string).toLowerCase()
const tokenSymbol: string = (res.tokenSymbol as string).toLowerCase()
const bonderAddress: string = (res.bonderAddress as string)
const isL1BridgeDeploy: boolean = res.isL1BridgeDeploy as boolean
const l2CanonicalTokenIsEth: boolean = res.l2CanonicalTokenIsEth as boolean
const deploymentStep: number = res.deploymentStep as number
const didSendBridgeFunds: number = res.didSendBridgeFunds as number
let obj =
{
l1NetworkName,
l2NetworkName,
tokenSymbol,
bonderAddress,
isL1BridgeDeploy,
l2CanonicalTokenIsEth,
deploymentStep,
didSendBridgeFunds
}
console.log(obj)
return obj
}
function validateInput (
l1NetworkName: string,
l2NetworkName: string,
tokenSymbol: string,
bonderAddress: string
) {
if (!l1NetworkName) {
throw new Error('L1 network name is invalid')
}
if (!l2NetworkName) {
throw new Error('L2 network name is invalid')
}
if (!tokenSymbol) {
throw new Error('Token symbol is invalid')
}
if (bonderAddress.length !== 42) {
throw new Error('Bonder address is invalid')
}
}
function setL1BridgeNetworkParams (
l1NetworkName: string,
l2NetworkName: string,
tokenSymbol: string,
bonderAddress: string
) {
const expectedTokenSymbolLetterCase: string = getTokenSymbolLetterCase(tokenSymbol)
const networkData: NetworkData = getNetworkDataByNetworkName(l1NetworkName)
const l1ChainId = networkData[l2NetworkName].l1ChainId
const l1CanonicalTokenAddress = networkData[l2NetworkName].tokens[expectedTokenSymbolLetterCase].l1CanonicalTokenAddress
updateConfigFile({
l1ChainId,
l1CanonicalTokenAddress,
bonderAddress
})
}
function setNetworkParams (
l1NetworkName: string,
l2NetworkName: string,
tokenSymbol: string,
bonderAddress: string,
l2CanonicalTokenIsEth: boolean
) {
const { l1BridgeAddress } = readConfigFile()
const expectedTokenSymbolLetterCase: string = getTokenSymbolLetterCase(tokenSymbol)
const networkData: NetworkData = getNetworkDataByNetworkName(l1NetworkName)
const {
l1ChainId,
l2ChainId,
l1MessengerAddress,
l2TokenBridgeAddress,
l2MessengerAddress,
tokens
} = networkData[l2NetworkName]
const {
l1CanonicalTokenAddress,
l2CanonicalTokenAddress,
l2HBridgeTokenName,
l2HBridgeTokenSymbol,
l2HBridgeTokenDecimals,
l2SwapLpTokenName,
l2SwapLpTokenSymbol,
liquidityProviderSendAmount
} = tokens[expectedTokenSymbolLetterCase]
const liquidityProviderAmmAmount: BigNumber = BigNumber.from(liquidityProviderSendAmount).div(2)
const data = {
l1ChainId,
l2ChainId,
l1BridgeAddress,
l1MessengerAddress,
l2TokenBridgeAddress,
l2MessengerAddress,
l1CanonicalTokenAddress,
l2CanonicalTokenAddress,
l2HBridgeTokenName,
l2HBridgeTokenSymbol,
l2HBridgeTokenDecimals,
l2SwapLpTokenName,
l2SwapLpTokenSymbol,
liquidityProviderSendAmount,
liquidityProviderAmmAmount: liquidityProviderAmmAmount.toString(),
bonderAddress,
l2CanonicalTokenIsEth
}
console.log('data:', data)
updateConfigFile(data)
}
function handleCustomL2NetworkName(l1NetworkName: string, l2NetworkName: string) {
if (l2NetworkName === 'optimism') {
if (l1NetworkName === 'mainnet') {
return 'optimism_mainnet'
} else if (l1NetworkName === 'kovan' || l1NetworkName === 'goerli') {
return l2NetworkName = 'optimism_testnet'
} else if (l1NetworkName === 'local' || l1NetworkName === 'local_l1'){
return l2NetworkName = 'localhost_l2'
}else{
throw new Error('Unknown L1 network name')
}
}
return l2NetworkName
}
main()
.then(() => {
process.exit(0)
})
.catch(error => {
logger.error(error)
process.exit(1)
})