Commit 2417d795 authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: check-l2 configurable url

Allows the URL to be configured via CLI params.

- `--rpc-url`

Also optionally accepts a chain id via CLI and asserts
that the remote chain id matches what is passed in via
CLI, only if a value is passed in via CLI.

- `--chain-id`

Can also skip the very long predeploy checking at the
beginning and add in some logs that ensure progress
is happening with `--skip-predeploy-check true`
parent f624cd21
import assert from 'assert'
import { task } from 'hardhat/config'
import { task, types } from 'hardhat/config'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import { Contract } from 'ethers'
import { Contract, providers, Wallet, Signer } from 'ethers'
import { predeploys } from '../src'
......@@ -28,7 +28,10 @@ const yell = (msg: string) => {
}
// checkPredeploys will ensure that all of the predeploys are set
const checkPredeploys = async (hre: HardhatRuntimeEnvironment) => {
const checkPredeploys = async (
hre: HardhatRuntimeEnvironment,
provider: providers.Provider
) => {
console.log('Checking predeploys are configured correctly')
for (let i = 0; i < 2048; i++) {
const num = hre.ethers.utils.hexZeroPad('0x' + i.toString(16), 2)
......@@ -36,7 +39,7 @@ const checkPredeploys = async (hre: HardhatRuntimeEnvironment) => {
hre.ethers.utils.hexConcat([prefix, num])
)
const code = await hre.ethers.provider.getCode(addr)
const code = await provider.getCode(addr)
if (code === '0x') {
throw new Error(`no code found at ${addr}`)
}
......@@ -49,7 +52,7 @@ const checkPredeploys = async (hre: HardhatRuntimeEnvironment) => {
continue
}
const slot = await hre.ethers.provider.getStorageAt(addr, adminSlot)
const slot = await provider.getStorageAt(addr, adminSlot)
const admin = hre.ethers.utils.hexConcat([
'0x000000000000000000000000',
predeploys.ProxyAdmin,
......@@ -58,6 +61,10 @@ const checkPredeploys = async (hre: HardhatRuntimeEnvironment) => {
if (admin !== slot) {
throw new Error(`incorrect admin slot in ${addr}`)
}
if (i % 200 === 0) {
console.log(`Checked through ${addr}`)
}
}
}
......@@ -81,36 +88,44 @@ const assertSemver = async (
}
// checkProxy will print out the proxy slots
const checkProxy = async (hre: HardhatRuntimeEnvironment, name: string) => {
const checkProxy = async (
_hre: HardhatRuntimeEnvironment,
name: string,
provider: providers.Provider
) => {
const address = predeploys[name]
if (!address) {
throw new Error(`unknown contract name: ${name}`)
}
const impl = await hre.ethers.provider.getStorageAt(address, implSlot)
const admin = await hre.ethers.provider.getStorageAt(address, adminSlot)
const impl = await provider.getStorageAt(address, implSlot)
const admin = await provider.getStorageAt(address, adminSlot)
console.log(` - EIP-1967 implementation slot: ${impl}`)
console.log(` - EIP-1967 admin slot: ${admin}`)
}
// assertProxy will require the proxy is set
const assertProxy = async (hre: HardhatRuntimeEnvironment, name: string) => {
const assertProxy = async (
hre: HardhatRuntimeEnvironment,
name: string,
provider: providers.Provider
) => {
const address = predeploys[name]
if (!address) {
throw new Error(`unknown contract name: ${name}`)
}
const code = await hre.ethers.provider.getCode(address)
const code = await provider.getCode(address)
const deployInfo = await hre.artifacts.readArtifact('Proxy')
if (code !== deployInfo.deployedBytecode) {
throw new Error(`${address}: code mismatch`)
}
const impl = await hre.ethers.provider.getStorageAt(address, implSlot)
const impl = await provider.getStorageAt(address, implSlot)
const implAddress = '0x' + impl.slice(26)
const implCode = await hre.ethers.provider.getCode(implAddress)
const implCode = await provider.getCode(implAddress)
if (implCode === '0x') {
throw new Error('No code at implementation')
}
......@@ -120,24 +135,29 @@ const check = {
// LegacyMessagePasser
// - check version
// - is behind a proxy
LegacyMessagePasser: async (hre: HardhatRuntimeEnvironment) => {
LegacyMessagePasser: async (
hre: HardhatRuntimeEnvironment,
signer: Signer
) => {
const LegacyMessagePasser = await hre.ethers.getContractAt(
'LegacyMessagePasser',
predeploys.LegacyMessagePasser
predeploys.LegacyMessagePasser,
signer
)
await assertSemver(LegacyMessagePasser, 'LegacyMessagePasser')
await checkProxy(hre, 'LegacyMessagePasser')
await assertProxy(hre, 'LegacyMessagePasser')
await checkProxy(hre, 'LegacyMessagePasser', signer.provider)
await assertProxy(hre, 'LegacyMessagePasser', signer.provider)
},
// DeployerWhitelist
// - check version
// - is behind a proxy
// - owner is `address(0)`
DeployerWhitelist: async (hre: HardhatRuntimeEnvironment) => {
DeployerWhitelist: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const DeployerWhitelist = await hre.ethers.getContractAt(
'DeployerWhitelist',
predeploys.DeployerWhitelist
predeploys.DeployerWhitelist,
signer
)
await assertSemver(DeployerWhitelist, 'DeployerWhitelist')
......@@ -146,8 +166,8 @@ const check = {
assert(owner === hre.ethers.constants.AddressZero)
console.log(` - owner: ${owner}`)
await checkProxy(hre, 'DeployerWhitelist')
await assertProxy(hre, 'DeployerWhitelist')
await checkProxy(hre, 'DeployerWhitelist', signer.provider)
await assertProxy(hre, 'DeployerWhitelist', signer.provider)
},
// L2CrossDomainMessenger
// - check version
......@@ -156,15 +176,19 @@ const check = {
// - is behind a proxy
// - check owner
// - check initialized
L2CrossDomainMessenger: async (hre: HardhatRuntimeEnvironment) => {
L2CrossDomainMessenger: async (
hre: HardhatRuntimeEnvironment,
signer: Signer
) => {
const L2CrossDomainMessenger = await hre.ethers.getContractAt(
'L2CrossDomainMessenger',
predeploys.L2CrossDomainMessenger
predeploys.L2CrossDomainMessenger,
signer
)
await assertSemver(L2CrossDomainMessenger, 'L2CrossDomainMessenger')
const xDomainMessageSenderSlot = await hre.ethers.provider.getStorageAt(
const xDomainMessageSenderSlot = await signer.provider.getStorageAt(
predeploys.L2CrossDomainMessenger,
204
)
......@@ -182,8 +206,8 @@ const check = {
await L2CrossDomainMessenger.l1CrossDomainMessenger()
yell(` - l1CrossDomainMessenger: ${l1CrossDomainMessenger}`)
await checkProxy(hre, 'L2CrossDomainMessenger')
await assertProxy(hre, 'L2CrossDomainMessenger')
await checkProxy(hre, 'L2CrossDomainMessenger', signer.provider)
await assertProxy(hre, 'L2CrossDomainMessenger', signer.provider)
const owner = await L2CrossDomainMessenger.owner()
assert(owner !== hre.ethers.constants.AddressZero)
......@@ -208,7 +232,7 @@ const check = {
` - MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR: ${MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR}`
)
const slot = await hre.ethers.provider.getStorageAt(
const slot = await signer.provider.getStorageAt(
predeploys.L2CrossDomainMessenger,
0
)
......@@ -223,10 +247,11 @@ const check = {
// GasPriceOracle
// - check version
// - check decimals
GasPriceOracle: async (hre: HardhatRuntimeEnvironment) => {
GasPriceOracle: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const GasPriceOracle = await hre.ethers.getContractAt(
'GasPriceOracle',
predeploys.GasPriceOracle
predeploys.GasPriceOracle,
signer
)
await assertSemver(GasPriceOracle, 'GasPriceOracle')
......@@ -235,15 +260,16 @@ const check = {
assert(decimals.eq(6))
console.log(` - decimals: ${decimals.toNumber()}`)
await checkProxy(hre, 'GasPriceOracle')
await assertProxy(hre, 'GasPriceOracle')
await checkProxy(hre, 'GasPriceOracle', signer.provider)
await assertProxy(hre, 'GasPriceOracle', signer.provider)
},
// L2StandardBridge
// - check version
L2StandardBridge: async (hre: HardhatRuntimeEnvironment) => {
L2StandardBridge: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const L2StandardBridge = await hre.ethers.getContractAt(
'L2StandardBridge',
predeploys.L2StandardBridge
predeploys.L2StandardBridge,
signer
)
await assertSemver(L2StandardBridge, 'L2StandardBridge')
......@@ -255,17 +281,18 @@ const check = {
const MESSENGER = await L2StandardBridge.MESSENGER()
assert(MESSENGER === predeploys.L2CrossDomainMessenger)
await checkProxy(hre, 'L2StandardBridge')
await assertProxy(hre, 'L2StandardBridge')
await checkProxy(hre, 'L2StandardBridge', signer.provider)
await assertProxy(hre, 'L2StandardBridge', signer.provider)
},
// SequencerFeeVault
// - check version
// - check RECIPIENT
// - check l1FeeWallet (legacy)
SequencerFeeVault: async (hre: HardhatRuntimeEnvironment) => {
SequencerFeeVault: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const SequencerFeeVault = await hre.ethers.getContractAt(
'SequencerFeeVault',
predeploys.SequencerFeeVault
predeploys.SequencerFeeVault,
signer
)
await assertSemver(SequencerFeeVault, 'SequencerFeeVault')
......@@ -282,54 +309,59 @@ const check = {
await SequencerFeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
await checkProxy(hre, 'SequencerFeeVault')
await assertProxy(hre, 'SequencerFeeVault')
await checkProxy(hre, 'SequencerFeeVault', signer.provider)
await assertProxy(hre, 'SequencerFeeVault', signer.provider)
},
// OptimismMintableERC20Factory
// - check version
OptimismMintableERC20Factory: async (hre: HardhatRuntimeEnvironment) => {
OptimismMintableERC20Factory: async (
hre: HardhatRuntimeEnvironment,
signer: Signer
) => {
const OptimismMintableERC20Factory = await hre.ethers.getContractAt(
'OptimismMintableERC20Factory',
predeploys.OptimismMintableERC20Factory
predeploys.OptimismMintableERC20Factory,
signer
)
await assertSemver(
OptimismMintableERC20Factory,
'OptimismMintableERC20Factory',
'1.0.0'
'OptimismMintableERC20Factory'
)
const BRIDGE = await OptimismMintableERC20Factory.BRIDGE()
assert(BRIDGE !== hre.ethers.constants.AddressZero)
await checkProxy(hre, 'OptimismMintableERC20Factory')
await assertProxy(hre, 'OptimismMintableERC20Factory')
await checkProxy(hre, 'OptimismMintableERC20Factory', signer.provider)
await assertProxy(hre, 'OptimismMintableERC20Factory', signer.provider)
},
// L1BlockNumber
// - check version
L1BlockNumber: async (hre: HardhatRuntimeEnvironment) => {
L1BlockNumber: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const L1BlockNumber = await hre.ethers.getContractAt(
'L1BlockNumber',
predeploys.L1BlockNumber
predeploys.L1BlockNumber,
signer
)
await assertSemver(L1BlockNumber, 'L1BlockNumber')
await checkProxy(hre, 'L1BlockNumber')
await assertProxy(hre, 'L1BlockNumber')
await checkProxy(hre, 'L1BlockNumber', signer.provider)
await assertProxy(hre, 'L1BlockNumber', signer.provider)
},
// L1Block
// - check version
L1Block: async (hre: HardhatRuntimeEnvironment) => {
L1Block: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const L1Block = await hre.ethers.getContractAt(
'L1Block',
predeploys.L1Block
predeploys.L1Block,
signer
)
await assertSemver(L1Block, 'L1Block')
await checkProxy(hre, 'L1Block')
await assertProxy(hre, 'L1Block')
await checkProxy(hre, 'L1Block', signer.provider)
await assertProxy(hre, 'L1Block', signer.provider)
},
// LegacyERC20ETH
// - not behind a proxy
......@@ -339,10 +371,11 @@ const check = {
// - check BRIDGE
// - check REMOTE_TOKEN
// - totalSupply should be set to 0
LegacyERC20ETH: async (hre: HardhatRuntimeEnvironment) => {
LegacyERC20ETH: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const LegacyERC20ETH = await hre.ethers.getContractAt(
'LegacyERC20ETH',
predeploys.LegacyERC20ETH
predeploys.LegacyERC20ETH,
signer
)
const name = await LegacyERC20ETH.name()
......@@ -367,15 +400,19 @@ const check = {
assert(totalSupply.eq(0))
console.log(` - totalSupply: ${totalSupply}`)
await checkProxy(hre, 'LegacyERC20ETH')
await checkProxy(hre, 'LegacyERC20ETH', signer.provider)
// No proxy at this address, don't call assertProxy
},
// WETH9
// - check name
// - check symbol
// - check decimals
WETH9: async (hre: HardhatRuntimeEnvironment) => {
const WETH9 = await hre.ethers.getContractAt('WETH9', predeploys.WETH9)
WETH9: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const WETH9 = await hre.ethers.getContractAt(
'WETH9',
predeploys.WETH9,
signer
)
const name = await WETH9.name()
assert(name === 'Wrapped Ether')
......@@ -394,10 +431,11 @@ const check = {
// - check name
// - check symbol
// - check owner
GovernanceToken: async (hre: HardhatRuntimeEnvironment) => {
GovernanceToken: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const GovernanceToken = await hre.ethers.getContractAt(
'GovernanceToken',
predeploys.GovernanceToken
predeploys.GovernanceToken,
signer
)
const name = await GovernanceToken.name()
......@@ -414,15 +452,16 @@ const check = {
const totalSupply = await GovernanceToken.totalSupply()
console.log(` - totalSupply: ${totalSupply}`)
await checkProxy(hre, 'GovernanceToken')
await checkProxy(hre, 'GovernanceToken', signer.provider)
// No proxy at this address, don't call assertProxy
},
// L2ERC721Bridge
// - check version
L2ERC721Bridge: async (hre: HardhatRuntimeEnvironment) => {
L2ERC721Bridge: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const L2ERC721Bridge = await hre.ethers.getContractAt(
'L2ERC721Bridge',
predeploys.L2ERC721Bridge
predeploys.L2ERC721Bridge,
signer
)
await assertSemver(L2ERC721Bridge, 'L2ERC721Bridge')
......@@ -435,21 +474,24 @@ const check = {
assert(OTHER_BRIDGE !== hre.ethers.constants.AddressZero)
yell(` - OTHER_BRIDGE: ${OTHER_BRIDGE}`)
await checkProxy(hre, 'L2ERC721Bridge')
await assertProxy(hre, 'L2ERC721Bridge')
await checkProxy(hre, 'L2ERC721Bridge', signer.provider)
await assertProxy(hre, 'L2ERC721Bridge', signer.provider)
},
// OptimismMintableERC721Factory
// - check version
OptimismMintableERC721Factory: async (hre: HardhatRuntimeEnvironment) => {
OptimismMintableERC721Factory: async (
hre: HardhatRuntimeEnvironment,
signer: Signer
) => {
const OptimismMintableERC721Factory = await hre.ethers.getContractAt(
'OptimismMintableERC721Factory',
predeploys.OptimismMintableERC721Factory
predeploys.OptimismMintableERC721Factory,
signer
)
await assertSemver(
OptimismMintableERC721Factory,
'OptimismMintableERC721Factory',
'1.0.0'
'OptimismMintableERC721Factory'
)
const BRIDGE = await OptimismMintableERC721Factory.BRIDGE()
......@@ -461,15 +503,16 @@ const check = {
assert(REMOTE_CHAIN_ID !== 0)
console.log(` - REMOTE_CHAIN_ID: ${REMOTE_CHAIN_ID}`)
await checkProxy(hre, 'OptimismMintableERC721Factory')
await assertProxy(hre, 'OptimismMintableERC721Factory')
await checkProxy(hre, 'OptimismMintableERC721Factory', signer.provider)
await assertProxy(hre, 'OptimismMintableERC721Factory', signer.provider)
},
// ProxyAdmin
// - check owner
ProxyAdmin: async (hre: HardhatRuntimeEnvironment) => {
ProxyAdmin: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const ProxyAdmin = await hre.ethers.getContractAt(
'ProxyAdmin',
predeploys.ProxyAdmin
predeploys.ProxyAdmin,
signer
)
const owner = await ProxyAdmin.owner()
......@@ -483,10 +526,11 @@ const check = {
// - check version
// - check MIN_WITHDRAWAL_AMOUNT
// - check RECIPIENT
BaseFeeVault: async (hre: HardhatRuntimeEnvironment) => {
BaseFeeVault: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const BaseFeeVault = await hre.ethers.getContractAt(
'BaseFeeVault',
predeploys.BaseFeeVault
predeploys.BaseFeeVault,
signer
)
await assertSemver(BaseFeeVault, 'BaseFeeVault')
......@@ -498,17 +542,18 @@ const check = {
assert(RECIPIENT !== hre.ethers.constants.AddressZero)
yell(` - RECIPIENT: ${RECIPIENT}`)
await checkProxy(hre, 'BaseFeeVault')
await assertProxy(hre, 'BaseFeeVault')
await checkProxy(hre, 'BaseFeeVault', signer.provider)
await assertProxy(hre, 'BaseFeeVault', signer.provider)
},
// L1FeeVault
// - check version
// - check MIN_WITHDRAWAL_AMOUNT
// - check RECIPIENT
L1FeeVault: async (hre: HardhatRuntimeEnvironment) => {
L1FeeVault: async (hre: HardhatRuntimeEnvironment, signer: Signer) => {
const L1FeeVault = await hre.ethers.getContractAt(
'L1FeeVault',
predeploys.L1FeeVault
predeploys.L1FeeVault,
signer
)
await assertSemver(L1FeeVault, 'L1FeeVault')
......@@ -520,15 +565,19 @@ const check = {
assert(RECIPIENT !== hre.ethers.constants.AddressZero)
yell(` - RECIPIENT: ${RECIPIENT}`)
await checkProxy(hre, 'L1FeeVault')
await assertProxy(hre, 'L1FeeVault')
await checkProxy(hre, 'L1FeeVault', signer.provider)
await assertProxy(hre, 'L1FeeVault', signer.provider)
},
// L2ToL1MessagePasser
// - check version
L2ToL1MessagePasser: async (hre: HardhatRuntimeEnvironment) => {
L2ToL1MessagePasser: async (
hre: HardhatRuntimeEnvironment,
signer: Signer
) => {
const L2ToL1MessagePasser = await hre.ethers.getContractAt(
'L2ToL1MessagePasser',
predeploys.L2ToL1MessagePasser
predeploys.L2ToL1MessagePasser,
signer
)
await assertSemver(L2ToL1MessagePasser, 'L2ToL1MessagePasser')
......@@ -539,26 +588,55 @@ const check = {
const messageNonce = await L2ToL1MessagePasser.messageNonce()
console.log(` - messageNonce: ${messageNonce}`)
await checkProxy(hre, 'L2ToL1MessagePasser')
await assertProxy(hre, 'L2ToL1MessagePasser')
await checkProxy(hre, 'L2ToL1MessagePasser', signer.provider)
await assertProxy(hre, 'L2ToL1MessagePasser', signer.provider)
},
}
task(
'check-l2',
'Checks a freshly migrated L2 system for correct migration'
).setAction(async (_, hre: HardhatRuntimeEnvironment) => {
task('check-l2', 'Checks a freshly migrated L2 system for correct migration')
.addOptionalParam('rpcUrl', 'RPC URL of the remote node', '', types.string)
.addOptionalParam('chainId', 'Expected chain id', 0, types.int)
.addOptionalParam(
'skipPredeployCheck',
'Skip long check',
false,
types.boolean
)
.setAction(async (args, hre: HardhatRuntimeEnvironment) => {
yell('Manually check values wrapped in !!!!')
console.log()
let signer: Signer = hre.ethers.provider.getSigner()
if (args.rpcUrl !== '') {
console.log('Using CLI URL for provider instead of hardhat network')
const provider = new hre.ethers.providers.JsonRpcProvider(args.rpcUrl)
signer = Wallet.createRandom().connect(provider)
}
if (args.chainId !== 0) {
const chainId = await signer.getChainId()
if (chainId !== args.chainId) {
throw new Error(
`Unexpected Chain ID. Got ${chainId}, expected ${args.chainId}`
)
}
console.log(`Verified Chain ID: ${chainId}`)
} else {
console.log(`Skipping Chain ID validation...`)
}
// Ensure that all the predeploys exist, including the not
// currently configured ones
await checkPredeploys(hre)
if (!args.skipPredeployCheck) {
await checkPredeploys(hre, signer.provider)
}
console.log()
// Check the currently configured predeploys
for (const [name, fn] of Object.entries(check)) {
const address = predeploys[name]
console.log(`${name}: ${address}`)
await fn(hre)
await fn(hre, signer)
}
})
})
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