Commit 3e2700d1 authored by Georgios Konstantopoulos's avatar Georgios Konstantopoulos Committed by GitHub

feat: hardhat-deploy (#418)

* chore(hardhat-ovm): yarn lint:fix

* install hardhat-deploy

* refactor: move predeploys to own file

* feat: enable hardhat-deploy on hardhat config

* feat(contracts): add deployment steps

* feat(ops): copy over any additional build files

* ops: make scripts wait for more retries

hardhat-deploy is slower and requires re-compiling
parent 41cfbd16
...@@ -11,4 +11,4 @@ cache ...@@ -11,4 +11,4 @@ cache
cache-ovm cache-ovm
l2geth/build/bin l2geth/build/bin
packages/contracts/deployments/custom
...@@ -13,14 +13,30 @@ COPY --from=builder /optimism/node_modules ./node_modules ...@@ -13,14 +13,30 @@ COPY --from=builder /optimism/node_modules ./node_modules
COPY --from=builder /optimism/packages/core-utils/package.json ./packages/core-utils/package.json COPY --from=builder /optimism/packages/core-utils/package.json ./packages/core-utils/package.json
COPY --from=builder /optimism/packages/core-utils/dist ./packages/core-utils/dist COPY --from=builder /optimism/packages/core-utils/dist ./packages/core-utils/dist
# get the items COPY --from=builder /optimism/packages/hardhat-ovm/package.json ./packages/hardhat-ovm/package.json
COPY --from=builder /optimism/packages/hardhat-ovm/dist ./packages/hardhat-ovm/dist
# get the needed built artifacts
WORKDIR /opt/optimism/packages/contracts WORKDIR /opt/optimism/packages/contracts
COPY --from=builder /optimism/packages/contracts/dist ./dist COPY --from=builder /optimism/packages/contracts/dist ./dist
COPY --from=builder /optimism/packages/contracts/bin ./bin COPY --from=builder /optimism/packages/contracts/bin ./bin
COPY --from=builder /optimism/packages/contracts/package.json ./ COPY --from=builder /optimism/packages/contracts/*.json ./
COPY --from=builder /optimism/packages/contracts/node_modules ./node_modules COPY --from=builder /optimism/packages/contracts/node_modules ./node_modules
COPY --from=builder /optimism/packages/contracts/artifacts ./artifacts COPY --from=builder /optimism/packages/contracts/artifacts ./artifacts
COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./artifacts-ovm COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./artifacts-ovm
# copy over the cache so that hardhat-deploy does not recompile
COPY --from=builder /optimism/packages/contracts/cache ./cache
COPY --from=builder /optimism/packages/contracts/cache-ovm ./cache-ovm
# get the files for hardhat-deploy
COPY --from=builder /optimism/packages/contracts/contracts ./contracts
COPY --from=builder /optimism/packages/contracts/hardhat.config.ts ./
COPY --from=builder /optimism/packages/contracts/deploy ./deploy
COPY --from=builder /optimism/packages/contracts/tasks ./tasks
COPY --from=builder /optimism/packages/contracts/src ./src
COPY --from=builder /optimism/packages/contracts/test/helpers/constants.ts ./test/helpers/constants.ts
COPY --from=builder /optimism/packages/contracts/scripts ./scripts
COPY ./ops/scripts/deployer.sh . COPY ./ops/scripts/deployer.sh .
ENTRYPOINT yarn run deploy ENTRYPOINT yarn run deploy
#!/bin/bash #!/bin/bash
RETRIES=${RETRIES:-20} RETRIES=${RETRIES:-40}
# get the addrs from the URL provided # get the addrs from the URL provided
ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 3 $URL) ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL)
# set the env # set the env
export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager') export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager')
......
...@@ -5,9 +5,8 @@ JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' ...@@ -5,9 +5,8 @@ JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}'
# wait for the base layer to be up # wait for the base layer to be up
curl -H "Content-Type: application/json" --retry-connrefused --retry $RETRIES --retry-delay 1 -d $JSON $L1_NODE_WEB3_URL curl -H "Content-Type: application/json" --retry-connrefused --retry $RETRIES --retry-delay 1 -d $JSON $L1_NODE_WEB3_URL
# get the addrs to a var
ADDRESSES=$(yarn run --silent deploy) yarn run deploy
# sent them to the file
echo $ADDRESSES > dist/dumps/addresses.json
# serve the addrs and the state dump # serve the addrs and the state dump
./bin/serve_dump.sh ./bin/serve_dump.sh
#!/bin/bash #!/bin/bash
RETRIES=${RETRIES:-20} RETRIES=${RETRIES:-40}
# get the addrs from the URL provided # get the addrs from the URL provided
ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 2 $URL) ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL)
# set the env # set the env
export DATA_TRANSPORT_LAYER__ADDRESS_MANAGER=$(echo $ADDRESSES | jq -r '.AddressManager') export DATA_TRANSPORT_LAYER__ADDRESS_MANAGER=$(echo $ADDRESSES | jq -r '.AddressManager')
......
#!/bin/bash #!/bin/bash
RETRIES=${RETRIES:-20} RETRIES=${RETRIES:-40}
# get the addrs from the URL provided # get the addrs from the URL provided
ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 1 $URL) ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL)
function envSet() { function envSet() {
VAR=$1 VAR=$1
......
#!/bin/bash #!/bin/bash
RETRIES=${RETRIES:-20} RETRIES=${RETRIES:-40}
# get the addrs from the URL provided # get the addrs from the URL provided
ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 3 $URL) ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL)
# set the env # set the env
export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager') export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager')
......
#!/usr/bin/env node
const contracts = require('../dist/contract-deployment/deploy');
const { providers, Wallet, utils, ethers } = require('ethers');
const { JsonRpcProvider } = providers;
const fs = require('fs')
const env = process.env;
const key = env.DEPLOYER_PRIVATE_KEY;
const sequencerKey = env.SEQUENCER_PRIVATE_KEY;
let SEQUENCER_ADDRESS = env.SEQUENCER_ADDRESS;
const web3Url = env.L1_NODE_WEB3_URL || 'http://127.0.0.1:8545';
const DEPLOY_TX_GAS_LIMIT = env.DEPLOY_TX_GAS_LIMIT || 5000000;
const MIN_TRANSACTION_GAS_LIMIT = env.MIN_TRANSACTION_GAS_LIMIT || 50000;
const MAX_TRANSACTION_GAS_LIMIT = env.MAX_TRANSACTION_GAS_LIMIT || 9000000;
const MAX_GAS_PER_QUEUE_PER_EPOCH = env.MAX_GAS_PER_QUEUE_PER_EPOCH || 250000000;
const SECONDS_PER_EPOCH = env.SECONDS_PER_EPOCH || 0;
const WAIT_FOR_RECEIPTS = env.WAIT_FOR_RECEIPTS === 'true';
let WHITELIST_OWNER = env.WHITELIST_OWNER;
const WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT = env.WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT || true;
const FORCE_INCLUSION_PERIOD_SECONDS = env.FORCE_INCLUSION_PERIOD_SECONDS || 2592000; // 30 days
const FRAUD_PROOF_WINDOW_SECONDS = env.FRAUD_PROOF_WINDOW_SECONDS || (60 * 60 * 24 * 7); // 7 days
const SEQUENCER_PUBLISH_WINDOW_SECONDS = env.SEQUENCER_PUBLISH_WINDOW_SECONDS || (60 * 30); // 30 min
const CHAIN_ID = env.CHAIN_ID || 420; // layer 2 chainid
const ADDRESS_MANAGER_ADDRESS = env.ADDRESS_MANAGER_ADDRESS || undefined;
const BLOCK_TIME_SECONDS = env.BLOCK_TIME_SECONDS || 15;
const L2_CROSS_DOMAIN_MESSENGER_ADDRESS =
env.L2_CROSS_DOMAIN_MESSENGER_ADDRESS || '0x4200000000000000000000000000000000000007';
let RELAYER_ADDRESS = env.RELAYER_ADDRESS || '0x0000000000000000000000000000000000000000';
const RELAYER_PRIVATE_KEY = env.RELAYER_PRIVATE_KEY;
(async () => {
const provider = new JsonRpcProvider(web3Url);
if (typeof key === 'undefined') {
throw new Error('Must pass deployer key as DEPLOYER_PRIVATE_KEY');
}
const signer = new Wallet(key, provider);
if (SEQUENCER_ADDRESS) {
if (!utils.isAddress(SEQUENCER_ADDRESS))
throw new Error(`Invalid Sequencer Address: ${SEQUENCER_ADDRESS}`);
} else {
if (!sequencerKey)
throw new Error('Must pass sequencer key as SEQUENCER_PRIVATE_KEY');
const sequencer = new Wallet(sequencerKey, provider);
SEQUENCER_ADDRESS = await sequencer.getAddress();
}
if (typeof WHITELIST_OWNER === 'undefined')
WHITELIST_OWNER = signer;
// Use the address derived from RELAYER_PRIVATE_KEY if a private key
// is passed. Using the zero address as the relayer address will mean
// there is no relayer authentication.
if (RELAYER_PRIVATE_KEY) {
if (!utils.isAddress(RELAYER_ADDRESS))
throw new Error(`Invalid Relayer Address: ${RELAYER_ADDRESS}`);
const relayer = new Wallet(RELAYER_PRIVATE_KEY, provider);
RELAYER_ADDRESS = await relayer.getAddress();
}
const result = await contracts.deploy({
deploymentSigner: signer,
transactionChainConfig: {
forceInclusionPeriodSeconds: FORCE_INCLUSION_PERIOD_SECONDS,
sequencer: SEQUENCER_ADDRESS,
forceInclusionPeriodBlocks: Math.ceil(FORCE_INCLUSION_PERIOD_SECONDS/BLOCK_TIME_SECONDS),
},
stateChainConfig: {
fraudProofWindowSeconds: FRAUD_PROOF_WINDOW_SECONDS,
sequencerPublishWindowSeconds: SEQUENCER_PUBLISH_WINDOW_SECONDS,
},
ovmGlobalContext: {
ovmCHAINID: CHAIN_ID,
L2CrossDomainMessengerAddress: L2_CROSS_DOMAIN_MESSENGER_ADDRESS
},
l1CrossDomainMessengerConfig: {
relayerAddress: RELAYER_ADDRESS,
},
ovmGasMeteringConfig: {
minTransactionGasLimit: MIN_TRANSACTION_GAS_LIMIT,
maxTransactionGasLimit: MAX_TRANSACTION_GAS_LIMIT,
maxGasPerQueuePerEpoch: MAX_GAS_PER_QUEUE_PER_EPOCH,
secondsPerEpoch: SECONDS_PER_EPOCH
},
whitelistConfig: {
owner: WHITELIST_OWNER,
allowArbitraryContractDeployment: WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT
},
deployOverrides: {
gasLimit: DEPLOY_TX_GAS_LIMIT
},
waitForReceipts: WAIT_FOR_RECEIPTS,
addressManager: ADDRESS_MANAGER_ADDRESS,
});
const { failedDeployments, AddressManager } = result;
if (failedDeployments.length !== 0)
throw new Error(`Contract deployment failed: ${failedDeployments.join(',')}`);
const out = {};
out.AddressManager = AddressManager.address;
out.OVM_Sequencer = SEQUENCER_ADDRESS;
out.Deployer = await signer.getAddress()
for (const [name, contract] of Object.entries(result.contracts)) {
out[name] = contract.address;
}
const addresses = JSON.stringify(out, null, 2)
fs.writeFileSync(__dirname + "/addresses.json", addresses)
console.log(JSON.stringify(out, null, 2));
})().catch(err => {
console.log(JSON.stringify({error: err.message, stack: err.stack}, null, 2));
process.exit(1);
});
#!/usr/bin/env ts-node-script
import { Wallet } from 'ethers'
import path from 'path'
import dirtree from 'directory-tree'
import fs from 'fs'
// Ensures that all relevant environment vars are properly set. These lines *must* come before the
// hardhat import because importing will load the config (which relies on these vars). Necessary
// because CI currently uses different var names than the ones we've chosen here.
// TODO: Update CI so that we don't have to do this anymore.
process.env.HARDHAT_NETWORK = 'custom' // "custom" here is an arbitrary name. only used for CI.
process.env.CONTRACTS_TARGET_NETWORK = 'custom'
process.env.CONTRACTS_DEPLOYER_KEY = process.env.DEPLOYER_PRIVATE_KEY
process.env.CONTRACTS_RPC_URL =
process.env.L1_NODE_WEB3_URL || 'http://127.0.0.1:8545'
import hre from 'hardhat'
const main = async () => {
const sequencer = new Wallet(process.env.SEQUENCER_PRIVATE_KEY)
const deployer = new Wallet(process.env.DEPLOYER_PRIVATE_KEY)
await hre.run('deploy', {
l1BlockTimeSeconds: process.env.BLOCK_TIME_SECONDS,
ctcForceInclusionPeriodSeconds: process.env.FORCE_INCLUSION_PERIOD_SECONDS,
ctcMaxTransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT,
emMinTransactionGasLimit: process.env.MIN_TRANSACTION_GAS_LIMIT,
emMaxtransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT,
emMaxGasPerQueuePerEpoch: process.env.MAX_GAS_PER_QUEUE_PER_EPOCH,
emSecondsPerEpoch: process.env.SECONDS_PER_EPOCH,
emOvmChainId: process.env.CHAIN_ID,
sccFraudProofWindow: parseInt(process.env.FRAUD_PROOF_WINDOW_SECONDS, 10),
sccSequencerPublishWindow: process.env.SEQUENCER_PUBLISH_WINDOW_SECONDS,
ovmSequencerAddress: sequencer.address,
ovmProposerAddress: sequencer.address,
ovmRelayerAddress: sequencer.address,
ovmAddressManagerOwner: deployer.address,
})
// Stuff below this line is currently required for CI to work properly. We probably want to
// update our CI so this is no longer necessary. But I'm adding it for backwards compat so we can
// get the hardhat-deploy stuff merged. Woot.
const nicknames = {
'Lib_AddressManager': 'AddressManager',
'mockOVM_BondManager': 'OVM_BondManager'
}
const contracts = dirtree(
path.resolve(__dirname, `../deployments/custom`)
).children.filter((child) => {
return child.extension === '.json'
}).reduce((contracts, child) => {
const contractName = child.name.replace('.json', '')
const artifact = require(path.resolve(__dirname, `../deployments/custom/${child.name}`))
contracts[nicknames[contractName] || contractName] = artifact.address
return contracts
}, {})
const addresses = JSON.stringify(contracts, null, 2)
const dumpsPath = path.resolve(__dirname, "../dist/dumps")
if (!fs.existsSync(dumpsPath)) {
fs.mkdirSync(dumpsPath)
}
const addrsPath = path.resolve(dumpsPath, 'addresses.json')
fs.writeFileSync(addrsPath, addresses)
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.log(
JSON.stringify({ error: error.message, stack: error.stack }, null, 2)
)
process.exit(1)
})
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { registerAddress } from '../src/hardhat-deploy-ethers'
import { predeploys } from '../src/predeploys'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
await deploy('Lib_AddressManager', {
from: deployer,
args: [],
log: true,
})
await registerAddress({
hre,
name: 'OVM_L2CrossDomainMessenger',
address: predeploys.OVM_L2CrossDomainMessenger,
})
await registerAddress({
hre,
name: 'OVM_DecompressionPrecompileAddress',
address: predeploys.OVM_SequencerEntrypoint,
})
await registerAddress({
hre,
name: 'OVM_Sequencer',
address: (hre as any).deployConfig.ovmSequencerAddress,
})
await registerAddress({
hre,
name: 'OVM_Proposer',
address: (hre as any).deployConfig.ovmProposerAddress,
})
await registerAddress({
hre,
name: 'OVM_L2BatchMessageRelayer',
address: (hre as any).deployConfig.ovmRelayerAddress,
})
}
deployFn.tags = ['Lib_AddressManager', 'required']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_ChainStorageContainer:CTC:batches',
contract: 'OVM_ChainStorageContainer',
args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_ChainStorageContainer_ctc_batches']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_ChainStorageContainer:CTC:queue',
contract: 'OVM_ChainStorageContainer',
args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_ChainStorageContainer_ctc_queue']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_ChainStorageContainer:SCC:batches',
contract: 'OVM_ChainStorageContainer',
args: [Lib_AddressManager.address, 'OVM_StateCommitmentChain'],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_ChainStorageContainer_scc_batches']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_CanonicalTransactionChain',
args: [
Lib_AddressManager.address,
(hre as any).deployConfig.ctcForceInclusionPeriodSeconds,
(hre as any).deployConfig.ctcForceInclusionPeriodBlocks,
(hre as any).deployConfig.ctcMaxTransactionGasLimit,
],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_CanonicalTransactionChain']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_StateCommitmentChain',
args: [
Lib_AddressManager.address,
(hre as any).deployConfig.sccFraudProofWindow,
(hre as any).deployConfig.sccSequencerPublishWindow,
],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_StateCommitmentChain']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const result = await deploy('mockOVM_BondManager', {
from: deployer,
args: [Lib_AddressManager.address],
log: true,
})
if (!result.newlyDeployed) {
return
}
await Lib_AddressManager.setAddress('OVM_BondManager', result.address)
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['mockOVM_BondManager']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const result = await deploy('OVM_L1CrossDomainMessenger', {
from: deployer,
args: [],
log: true,
})
if (!result.newlyDeployed) {
return
}
const OVM_L1CrossDomainMessenger = await getDeployedContract(
hre,
'OVM_L1CrossDomainMessenger',
{
signerOrProvider: deployer,
}
)
// NOTE: this initialization is *not* technically required (we only need to initialize the proxy)
// but it feels safer to initialize this anyway. Otherwise someone else could come along and
// initialize this.
await OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address)
const libAddressManager = await OVM_L1CrossDomainMessenger.libAddressManager()
if (libAddressManager !== Lib_AddressManager.address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` +
`Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` +
`Actual address after initialization: ${libAddressManager}\n` +
`This could indicate a compromised deployment.`
)
}
await Lib_AddressManager.setAddress(
'OVM_L1CrossDomainMessenger',
result.address
)
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_L1CrossDomainMessenger']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const result = await deploy('Proxy__OVM_L1CrossDomainMessenger', {
contract: 'Lib_ResolvedDelegateProxy',
from: deployer,
args: [Lib_AddressManager.address, 'OVM_L1CrossDomainMessenger'],
log: true,
})
if (!result.newlyDeployed) {
return
}
const Proxy__OVM_L1CrossDomainMessenger = await getDeployedContract(
hre,
'Proxy__OVM_L1CrossDomainMessenger',
{
signerOrProvider: deployer,
iface: 'OVM_L1CrossDomainMessenger',
}
)
await Proxy__OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address)
const libAddressManager = await Proxy__OVM_L1CrossDomainMessenger.libAddressManager()
if (libAddressManager !== Lib_AddressManager.address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`Proxy__OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` +
`Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` +
`Actual address after initialization: ${libAddressManager}\n` +
`This could indicate a compromised deployment.`
)
}
await Lib_AddressManager.setAddress(
'Proxy__OVM_L1CrossDomainMessenger',
result.address
)
}
deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1CrossDomainMessenger']
deployFn.tags = ['Proxy__OVM_L1CrossDomainMessenger']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_ExecutionManager',
args: [
Lib_AddressManager.address,
{
minTransactionGasLimit: (hre as any).deployConfig
.emMinTransactionGasLimit,
maxTransactionGasLimit: (hre as any).deployConfig
.emMaxTransactionGasLimit,
maxGasPerQueuePerEpoch: (hre as any).deployConfig
.emMaxGasPerQueuePerEpoch,
secondsPerEpoch: (hre as any).deployConfig.emSecondsPerEpoch,
},
{
ovmCHAINID: (hre as any).deployConfig.emOvmChainId,
},
],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_ExecutionManager']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_FraudVerifier',
args: [Lib_AddressManager.address],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_FraudVerifier']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { deployAndRegister } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
await deployAndRegister({
hre,
name: 'OVM_StateManagerFactory',
args: [],
})
}
deployFn.tags = ['OVM_FraudVerifier']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_StateTransitionerFactory',
args: [Lib_AddressManager.address],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_StateTransitionerFactory']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { deployAndRegister } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
await deployAndRegister({
hre,
name: 'OVM_SafetyChecker',
args: [],
})
}
deployFn.tags = ['OVM_SafetyChecker']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import {
deployAndRegister,
getDeployedContract,
} from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager'
)
await deployAndRegister({
hre,
name: 'OVM_L1MultiMessageRelayer',
args: [Lib_AddressManager.address],
})
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_L1MultiMessageRelayer']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
import { predeploys } from '../src/predeploys'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const result = await deploy('OVM_L1ETHGateway', {
from: deployer,
args: [],
log: true,
})
if (!result.newlyDeployed) {
return
}
const OVM_L1ETHGateway = await getDeployedContract(hre, 'OVM_L1ETHGateway', {
signerOrProvider: deployer,
})
// NOTE: this initialization is *not* technically required (we only need to initialize the proxy)
// but it feels safer to initialize this anyway. Otherwise someone else could come along and
// initialize this.
await OVM_L1ETHGateway.initialize(
Lib_AddressManager.address,
predeploys.OVM_ETH
)
const libAddressManager = await OVM_L1ETHGateway.libAddressManager()
if (libAddressManager !== Lib_AddressManager.address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`OVM_L1ETHGateway could not be succesfully initialized.\n` +
`Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` +
`Actual address after initialization: ${libAddressManager}\n` +
`This could indicate a compromised deployment.`
)
}
await Lib_AddressManager.setAddress('OVM_L1ETHGateway', result.address)
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['OVM_L1ETHGateway']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
import { predeploys } from '../src/predeploys'
const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const result = await deploy('Proxy__OVM_L1ETHGateway', {
contract: 'Lib_ResolvedDelegateProxy',
from: deployer,
args: [Lib_AddressManager.address, 'OVM_L1ETHGateway'],
log: true,
})
if (!result.newlyDeployed) {
return
}
const Proxy__OVM_L1ETHGateway = await getDeployedContract(
hre,
'Proxy__OVM_L1ETHGateway',
{
signerOrProvider: deployer,
iface: 'OVM_L1ETHGateway',
}
)
await Proxy__OVM_L1ETHGateway.initialize(
Lib_AddressManager.address,
predeploys.OVM_ETH
)
const libAddressManager = await Proxy__OVM_L1ETHGateway.libAddressManager()
if (libAddressManager !== Lib_AddressManager.address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`Proxy__OVM_L1ETHGateway could not be succesfully initialized.\n` +
`Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` +
`Actual address after initialization: ${libAddressManager}\n` +
`This could indicate a compromised deployment.`
)
}
await Lib_AddressManager.setAddress('Proxy__OVM_L1ETHGateway', result.address)
}
deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1ETHGateway']
deployFn.tags = ['Proxy__OVM_L1ETHGateway']
export default deployFn
/* Imports: External */
import { DeployFunction } from 'hardhat-deploy/dist/types'
/* Imports: Internal */
import { getDeployedContract } from '../src/hardhat-deploy-ethers'
const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const owner = (hre as any).deployConfig.ovmAddressManagerOwner
const remoteOwner = await Lib_AddressManager.owner()
if (remoteOwner === owner) {
console.log(
`✓ Not changing owner of Lib_AddressManager because it's already correctly set`
)
return
}
console.log(`Transferring ownership of Lib_AddressManager to ${owner}...`)
const tx = await Lib_AddressManager.transferOwnership(owner)
await tx.wait()
const newRemoteOwner = await Lib_AddressManager.owner()
if (newRemoteOwner !== owner) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`Could not transfer ownership of Lib_AddressManager.\n` +
`Attempted to set owner of Lib_AddressManager to: ${owner}\n` +
`Actual owner after transaction: ${newRemoteOwner}\n` +
`This could indicate a compromised deployment.`
)
}
console.log(`✓ Set owner of Lib_AddressManager to: ${owner}`)
}
deployFn.dependencies = ['Lib_AddressManager']
deployFn.tags = ['finalize']
export default deployFn
import { HardhatUserConfig } from 'hardhat/types' import { HardhatUserConfig } from 'hardhat/types'
import 'solidity-coverage' import 'solidity-coverage'
import * as dotenv from 'dotenv'
import { import {
DEFAULT_ACCOUNTS_HARDHAT, DEFAULT_ACCOUNTS_HARDHAT,
...@@ -9,19 +10,28 @@ import { ...@@ -9,19 +10,28 @@ import {
// Hardhat plugins // Hardhat plugins
import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-ethers'
import '@nomiclabs/hardhat-waffle' import '@nomiclabs/hardhat-waffle'
import 'hardhat-deploy'
import '@typechain/hardhat' import '@typechain/hardhat'
import '@eth-optimism/hardhat-ovm' import '@eth-optimism/hardhat-ovm'
import './tasks/deploy'
// Load environment variables from .env
dotenv.config()
const config: HardhatUserConfig = { const config: HardhatUserConfig = {
networks: { networks: {
hardhat: { hardhat: {
accounts: DEFAULT_ACCOUNTS_HARDHAT, accounts: DEFAULT_ACCOUNTS_HARDHAT,
blockGasLimit: RUN_OVM_TEST_GAS * 2, blockGasLimit: RUN_OVM_TEST_GAS * 2,
live: false,
saveDeployments: false,
tags: ['local'],
}, },
// Add this network to your config! // Add this network to your config!
optimism: { optimism: {
url: 'http://127.0.0.1:8545', url: 'http://127.0.0.1:8545',
ovm: true, ovm: true,
saveDeployments: false,
}, },
}, },
mocha: { mocha: {
...@@ -42,6 +52,29 @@ const config: HardhatUserConfig = { ...@@ -42,6 +52,29 @@ const config: HardhatUserConfig = {
outDir: 'dist/types', outDir: 'dist/types',
target: 'ethers-v5', target: 'ethers-v5',
}, },
paths: {
deploy: './deploy',
deployments: './deployments',
},
namedAccounts: {
deployer: {
default: 0,
},
},
}
if (
process.env.CONTRACTS_TARGET_NETWORK &&
process.env.CONTRACTS_DEPLOYER_KEY &&
process.env.CONTRACTS_RPC_URL
) {
config.networks[process.env.CONTRACTS_TARGET_NETWORK] = {
accounts: [process.env.CONTRACTS_DEPLOYER_KEY],
url: process.env.CONTRACTS_RPC_URL,
live: true,
saveDeployments: true,
tags: [process.env.CONTRACTS_TARGET_NETWORK],
}
} }
export default config export default config
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
"lint:fix": "yarn run lint:fix:typescript", "lint:fix": "yarn run lint:fix:typescript",
"lint:fix:typescript": "prettier --config prettier-config.json --write \"hardhat.config.ts\" \"{src,test}/**/*.ts\"", "lint:fix:typescript": "prettier --config prettier-config.json --write \"hardhat.config.ts\" \"{src,test}/**/*.ts\"",
"clean": "rm -rf ./dist ./artifacts ./artifacts-ovm ./cache ./cache-ovm ./tsconfig.build.tsbuildinfo", "clean": "rm -rf ./dist ./artifacts ./artifacts-ovm ./cache ./cache-ovm ./tsconfig.build.tsbuildinfo",
"deploy": "./bin/deploy.js", "deploy": "./bin/deploy.ts",
"serve": "./bin/serve_dump.sh" "serve": "./bin/serve_dump.sh"
}, },
"dependencies": { "dependencies": {
...@@ -53,9 +53,12 @@ ...@@ -53,9 +53,12 @@
"buffer-xor": "^2.0.2", "buffer-xor": "^2.0.2",
"chai": "^4.3.1", "chai": "^4.3.1",
"copyfiles": "^2.3.0", "copyfiles": "^2.3.0",
"directory-tree": "^2.2.7",
"dotenv": "^8.2.0",
"ethereum-waffle": "^3.3.0", "ethereum-waffle": "^3.3.0",
"ethers": "^5.0.31", "ethers": "^5.0.31",
"hardhat": "^2.0.8", "hardhat": "^2.0.8",
"hardhat-deploy": "^0.7.4",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"merkle-patricia-tree": "^4.0.0", "merkle-patricia-tree": "^4.0.0",
"merkletreejs": "^0.2.12", "merkletreejs": "^0.2.12",
...@@ -65,6 +68,7 @@ ...@@ -65,6 +68,7 @@
"rlp": "^2.2.6", "rlp": "^2.2.6",
"solidity-coverage": "^0.7.16", "solidity-coverage": "^0.7.16",
"ts-generator": "0.0.8", "ts-generator": "0.0.8",
"ts-node": "^9.1.1",
"typechain": "2.0.0" "typechain": "2.0.0"
}, },
"peerDependencies": { "peerDependencies": {
......
...@@ -8,6 +8,7 @@ import { fromHexString, toHexString, remove0x } from '@eth-optimism/core-utils' ...@@ -8,6 +8,7 @@ import { fromHexString, toHexString, remove0x } from '@eth-optimism/core-utils'
/* Internal Imports */ /* Internal Imports */
import { deploy, RollupDeployConfig } from './contract-deployment' import { deploy, RollupDeployConfig } from './contract-deployment'
import { getContractDefinition } from './contract-defs' import { getContractDefinition } from './contract-defs'
import { predeploys } from './predeploys'
interface StorageDump { interface StorageDump {
[key: string]: string [key: string]: string
...@@ -160,19 +161,6 @@ export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => { ...@@ -160,19 +161,6 @@ export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => {
config = { ...config, ...cfg } config = { ...config, ...cfg }
const predeploys = {
OVM_L2ToL1MessagePasser: '0x4200000000000000000000000000000000000000',
OVM_L1MessageSender: '0x4200000000000000000000000000000000000001',
OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002',
OVM_ECDSAContractAccount: '0x4200000000000000000000000000000000000003',
OVM_ProxySequencerEntrypoint: '0x4200000000000000000000000000000000000004',
OVM_SequencerEntrypoint: '0x4200000000000000000000000000000000000005',
OVM_ETH: '0x4200000000000000000000000000000000000006',
OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007',
Lib_AddressManager: '0x4200000000000000000000000000000000000008',
ERC1820Registry: '0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24',
}
const ovmCompiled = [ const ovmCompiled = [
'OVM_L2ToL1MessagePasser', 'OVM_L2ToL1MessagePasser',
'OVM_L2CrossDomainMessenger', 'OVM_L2CrossDomainMessenger',
......
/* Imports: External */
import { Contract } from 'ethers'
import { Provider } from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer'
export const registerAddress = async ({
hre,
name,
address,
}): Promise<void> => {
// TODO: Cache these 2 across calls?
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const currentAddress = await Lib_AddressManager.getAddress(name)
if (address === currentAddress) {
console.log(
`✓ Not registering address for ${name} because it's already been correctly registered`
)
return
}
console.log(`Registering address for ${name} to ${address}...`)
const tx = await Lib_AddressManager.setAddress(name, address)
await tx.wait()
const remoteAddress = await Lib_AddressManager.getAddress(name)
if (remoteAddress !== address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`Call to Lib_AddressManager.setAddress(${name}) was unsuccessful.\n` +
`Attempted to set address to: ${address}\n` +
`Actual address was set to: ${remoteAddress}\n` +
`This could indicate a compromised deployment.`
)
}
console.log(`✓ Registered address for ${name}`)
}
export const deployAndRegister = async ({
hre,
name,
args,
contract,
}: {
hre: any
name: string
args: any[]
contract?: string
}) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const result = await deploy(name, {
contract,
from: deployer,
args,
log: true,
})
await hre.ethers.provider.waitForTransaction(result.transactionHash)
if (result.newlyDeployed) {
await registerAddress({
hre,
name,
address: result.address,
})
}
}
export const getDeployedContract = async (
hre: any,
name: string,
options: {
iface?: string
signerOrProvider?: Signer | Provider | string
} = {}
): Promise<Contract> => {
const deployed = await hre.deployments.get(name)
await hre.ethers.provider.waitForTransaction(deployed.receipt.transactionHash)
// Get the correct interface.
let iface = new hre.ethers.utils.Interface(deployed.abi)
if (options.iface) {
const factory = await hre.ethers.getContractFactory(options.iface)
iface = factory.interface
}
let signerOrProvider: Signer | Provider = hre.ethers.provider
if (options.signerOrProvider) {
if (typeof options.signerOrProvider === 'string') {
signerOrProvider = hre.ethers.provider.getSigner(options.signerOrProvider)
} else {
signerOrProvider = options.signerOrProvider
}
}
// Temporarily override Object.defineProperty to bypass ether's object protection.
const def = Object.defineProperty
Object.defineProperty = (obj, propName, prop) => {
prop.writable = true
return def(obj, propName, prop)
}
const contract = new Contract(deployed.address, iface, signerOrProvider)
// Now reset Object.defineProperty
Object.defineProperty = def
// Override each function call to also `.wait()` so as to simplify the deploy scripts' syntax.
for (const fnName of Object.keys(contract.functions)) {
const fn = contract[fnName].bind(contract)
;(contract as any)[fnName] = async (...args: any) => {
const result = await fn(...args)
if (typeof result === 'object' && typeof result.wait === 'function') {
await result.wait()
}
return result
}
}
return contract
}
export const predeploys = {
OVM_L2ToL1MessagePasser: '0x4200000000000000000000000000000000000000',
OVM_L1MessageSender: '0x4200000000000000000000000000000000000001',
OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002',
OVM_ECDSAContractAccount: '0x4200000000000000000000000000000000000003',
OVM_ProxySequencerEntrypoint: '0x4200000000000000000000000000000000000004',
OVM_SequencerEntrypoint: '0x4200000000000000000000000000000000000005',
OVM_ETH: '0x4200000000000000000000000000000000000006',
OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007',
Lib_AddressManager: '0x4200000000000000000000000000000000000008',
ERC1820Registry: '0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24',
}
/* Imports: External */
import { ethers } from 'ethers'
import { task } from 'hardhat/config'
import * as types from 'hardhat/internal/core/params/argumentTypes'
const DEFAULT_L1_BLOCK_TIME_SECONDS = 15
const DEFAULT_CTC_FORCE_INCLUSION_PERIOD_SECONDS = 60 * 60 * 24 * 30 // 30 days
const DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT = 9_000_000
const DEFAULT_EM_MIN_TRANSACTION_GAS_LIMIT = 50_000
const DEFAULT_EM_MAX_TRANSACTION_GAS_LIMIT = 9_000_000
const DEFAULT_EM_MAX_GAS_PER_QUEUE_PER_EPOCH = 250_000_000
const DEFAULT_EM_SECONDS_PER_EPOCH = 0
const DEFAULT_EM_OVM_CHAIN_ID = 420
const DEFAULT_SCC_FRAUD_PROOF_WINDOW = 60 * 60 * 24 * 7 // 7 days
const DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW = 60 * 30 // 30 minutes
task('deploy')
.addOptionalParam(
'l1BlockTimeSeconds',
'Number of seconds on average between every L1 block.',
DEFAULT_L1_BLOCK_TIME_SECONDS,
types.int
)
.addOptionalParam(
'ctcForceInclusionPeriodSeconds',
'Number of seconds that the sequencer has to include transactions before the L1 queue.',
DEFAULT_CTC_FORCE_INCLUSION_PERIOD_SECONDS,
types.int
)
.addOptionalParam(
'ctcMaxTransactionGasLimit',
'Max gas limit for L1 queue transactions.',
DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT,
types.int
)
.addOptionalParam(
'emMinTransactionGasLimit',
'Minimum allowed transaction gas limit.',
DEFAULT_EM_MIN_TRANSACTION_GAS_LIMIT,
types.int
)
.addOptionalParam(
'emMaxTransactionGasLimit',
'Maximum allowed transaction gas limit.',
DEFAULT_EM_MAX_TRANSACTION_GAS_LIMIT,
types.int
)
.addOptionalParam(
'emMaxGasPerQueuePerEpoch',
'Maximum gas allowed in a given queue for each epoch.',
DEFAULT_EM_MAX_GAS_PER_QUEUE_PER_EPOCH,
types.int
)
.addOptionalParam(
'emSecondsPerEpoch',
'Number of seconds in each epoch.',
DEFAULT_EM_SECONDS_PER_EPOCH,
types.int
)
.addOptionalParam(
'emOvmChainId',
'Chain ID for the L2 network.',
DEFAULT_EM_OVM_CHAIN_ID,
types.int
)
.addOptionalParam(
'sccFraudProofWindow',
'Number of seconds until a transaction is considered finalized.',
DEFAULT_SCC_FRAUD_PROOF_WINDOW,
types.int
)
.addOptionalParam(
'sccSequencerPublishWindow',
'Number of seconds that the sequencer is exclusively allowed to post state roots.',
DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW,
types.int
)
.addOptionalParam(
'ovmSequencerAddress',
'Address of the sequencer. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'ovmProposerAddress',
'Address of the account that will propose state roots. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'ovmRelayerAddress',
'Address of the message relayer. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'ovmAddressManagerOwner',
'Address that will own the Lib_AddressManager. Must be provided or this deployment will fail.',
undefined,
types.string
)
.setAction(async (args, hre: any, runSuper) => {
// Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks.
const validateAddressArg = (argName: string) => {
if (args[argName] === undefined) {
throw new Error(
`argument for ${argName} is required but was not provided`
)
}
if (!ethers.utils.isAddress(args[argName])) {
throw new Error(
`argument for ${argName} is not a valid address: ${args[argName]}`
)
}
}
validateAddressArg('ovmSequencerAddress')
validateAddressArg('ovmProposerAddress')
validateAddressArg('ovmRelayerAddress')
validateAddressArg('ovmAddressManagerOwner')
args.ctcForceInclusionPeriodBlocks = Math.floor(
args.ctcForceInclusionPeriodSeconds / args.l1BlockTimeSeconds
)
hre.deployConfig = args
return runSuper(args)
})
...@@ -75,16 +75,23 @@ const getOvmSolcPath = async (version: string): Promise<string> => { ...@@ -75,16 +75,23 @@ const getOvmSolcPath = async (version: string): Promise<string> => {
subtask( subtask(
TASK_COMPILE_SOLIDITY_RUN_SOLC, TASK_COMPILE_SOLIDITY_RUN_SOLC,
async (args: { input: any; solcPath: string }, hre, runSuper) => { async (args: { input: any; solcPath: string }, hre, runSuper) => {
const ignoreRxList = hre.network.config.ignoreRxList || []; const ignoreRxList = hre.network.config.ignoreRxList || []
const ignore = (filename: string) => ignoreRxList.reduce((ignored: boolean, rx: string | RegExp) => ignored || new RegExp(rx).test(filename), false); const ignore = (filename: string) =>
ignoreRxList.reduce(
(ignored: boolean, rx: string | RegExp) =>
ignored || new RegExp(rx).test(filename),
false
)
if (hre.network.ovm !== true) { if (hre.network.ovm !== true) {
// Separate the EVM and OVM inputs. // Separate the EVM and OVM inputs.
for (const file of Object.keys(args.input.sources)) { for (const file of Object.keys(args.input.sources)) {
// Ignore any contract that has this tag or in ignore list // Ignore any contract that has this tag or in ignore list
if (args.input.sources[file].content.includes('// @unsupported: evm') || ignore(file)) { if (
delete args.input.sources[file]; args.input.sources[file].content.includes('// @unsupported: evm') ||
} ignore(file)
else { ) {
delete args.input.sources[file]
} else {
//console.log(file + ' included'); //console.log(file + ' included');
} }
} }
...@@ -114,7 +121,10 @@ subtask( ...@@ -114,7 +121,10 @@ subtask(
// Separate the EVM and OVM inputs. // Separate the EVM and OVM inputs.
for (const file of Object.keys(args.input.sources)) { for (const file of Object.keys(args.input.sources)) {
// Ignore any contract that has this tag or in ignore list // Ignore any contract that has this tag or in ignore list
if (!args.input.sources[file].content.includes('// @unsupported: ovm') && !ignore(file)) { if (
!args.input.sources[file].content.includes('// @unsupported: ovm') &&
!ignore(file)
) {
ovmInput.sources[file] = args.input.sources[file] ovmInput.sources[file] = args.input.sources[file]
} }
} }
...@@ -153,8 +163,8 @@ extendEnvironment((hre) => { ...@@ -153,8 +163,8 @@ extendEnvironment((hre) => {
} }
// Forcibly update the artifacts object. // Forcibly update the artifacts object.
hre.config.paths.artifacts = artifactsPath; hre.config.paths.artifacts = artifactsPath
hre.config.paths.cache = cachePath; hre.config.paths.cache = cachePath
(hre as any).artifacts = new Artifacts(artifactsPath); ;(hre as any).artifacts = new Artifacts(artifactsPath)
} }
}) })
...@@ -14,31 +14,29 @@ declare module 'hardhat/types/config' { ...@@ -14,31 +14,29 @@ declare module 'hardhat/types/config' {
} }
interface HardhatNetworkUserConfig { interface HardhatNetworkUserConfig {
ovm?: boolean; ovm?: boolean
ignoreRxList?: string[]; ignoreRxList?: string[]
} }
interface HttpNetworkUserConfig { interface HttpNetworkUserConfig {
ovm?: boolean; ovm?: boolean
ignoreRxList?: string[]; ignoreRxList?: string[]
} }
interface HardhatNetworkConfig { interface HardhatNetworkConfig {
ovm: boolean; ovm: boolean
ignoreRxList: string[]; ignoreRxList: string[]
} }
interface HttpNetworkConfig { interface HttpNetworkConfig {
ovm: boolean; ovm: boolean
ignoreRxList: string[]; ignoreRxList: string[]
} }
} }
declare module 'hardhat/types/runtime' { declare module 'hardhat/types/runtime' {
interface Network { interface Network {
ovm: boolean; ovm: boolean
ignoreRxList: string[]; ignoreRxList: string[]
} }
} }
This diff is collapsed.
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