Commit 5ae256f5 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge branch 'develop' into regenesis/0.4.0

parents 257deb70 735cd78f
---
'@eth-optimism/contracts': patch
---
"Adds connectL1Contracts and connectL2Contracts utility functions"
---
'@eth-optimism/message-relayer': patch
---
Update relayer package JSON to correctly export all files in dist
---
'@eth-optimism/integration-tests': patch
'@eth-optimism/data-transport-layer': patch
---
Add replica sync test to integration tests; handle 0 L2 blocks in DTL
...@@ -34,6 +34,7 @@ jobs: ...@@ -34,6 +34,7 @@ jobs:
working-directory: ./integration-tests working-directory: ./integration-tests
run: | run: |
yarn yarn
yarn build:integration
yarn test:sync yarn test:sync
- name: Collect docker logs on failure - name: Collect docker logs on failure
......
...@@ -2,7 +2,12 @@ import chai, { expect } from 'chai' ...@@ -2,7 +2,12 @@ import chai, { expect } from 'chai'
import { Wallet, BigNumber, providers } from 'ethers' import { Wallet, BigNumber, providers } from 'ethers'
import { injectL2Context } from '@eth-optimism/core-utils' import { injectL2Context } from '@eth-optimism/core-utils'
import { sleep, l2Provider, verifierProvider } from '../test/shared/utils' import {
sleep,
l2Provider,
verifierProvider,
waitForL2Geth,
} from '../test/shared/utils'
import { OptimismEnv } from '../test/shared/env' import { OptimismEnv } from '../test/shared/env'
import { DockerComposeNetwork } from '../test/shared/docker-compose' import { DockerComposeNetwork } from '../test/shared/docker-compose'
...@@ -33,14 +38,7 @@ describe('Syncing a verifier', () => { ...@@ -33,14 +38,7 @@ describe('Syncing a verifier', () => {
verifier = new DockerComposeNetwork(['verifier']) verifier = new DockerComposeNetwork(['verifier'])
await verifier.up({ commandOptions: ['--scale', 'verifier=1'] }) await verifier.up({ commandOptions: ['--scale', 'verifier=1'] })
// Wait for verifier to be looping provider = await waitForL2Geth(verifierProvider)
let logs = await verifier.logs()
while (!logs.out.includes('Starting Sequencer Loop')) {
await sleep(500)
logs = await verifier.logs()
}
provider = injectL2Context(verifierProvider)
} }
const syncVerifier = async (sequencerBlockNumber: number) => { const syncVerifier = async (sequencerBlockNumber: number) => {
......
import chai, { expect } from 'chai'
import { Wallet, Contract, ContractFactory, providers } from 'ethers'
import { ethers } from 'hardhat'
import { injectL2Context } from '@eth-optimism/core-utils'
import {
sleep,
l2Provider,
replicaProvider,
waitForL2Geth,
} from '../test/shared/utils'
import { OptimismEnv } from '../test/shared/env'
import { DockerComposeNetwork } from '../test/shared/docker-compose'
describe('Syncing a replica', () => {
let env: OptimismEnv
let wallet: Wallet
let replica: DockerComposeNetwork
let provider: providers.JsonRpcProvider
const sequencerProvider = injectL2Context(l2Provider)
/* Helper functions */
const startReplica = async () => {
// Bring up new replica
replica = new DockerComposeNetwork(['replica'])
await replica.up({
commandOptions: ['--scale', 'replica=1'],
})
provider = await waitForL2Geth(replicaProvider)
}
const syncReplica = async (sequencerBlockNumber: number) => {
// Wait until replica has caught up to the sequencer
let latestReplicaBlock = (await provider.getBlock('latest')) as any
while (latestReplicaBlock.number < sequencerBlockNumber) {
await sleep(500)
latestReplicaBlock = (await provider.getBlock('latest')) as any
}
return provider.getBlock(sequencerBlockNumber)
}
before(async () => {
env = await OptimismEnv.new()
wallet = env.l2Wallet
})
after(async () => {
await replica.stop('replica')
await replica.rm()
})
describe('Basic transactions and ERC20s', () => {
const initialAmount = 1000
const tokenName = 'OVM Test'
const tokenDecimals = 8
const TokenSymbol = 'OVM'
let other: Wallet
let Factory__ERC20: ContractFactory
let ERC20: Contract
before(async () => {
other = Wallet.createRandom().connect(ethers.provider)
Factory__ERC20 = await ethers.getContractFactory('ERC20', wallet)
})
it('should sync dummy transaction', async () => {
const tx = {
to: '0x' + '1234'.repeat(10),
gasLimit: 4000000,
gasPrice: 0,
data: '0x',
value: 0,
}
const result = await wallet.sendTransaction(tx)
await result.wait()
const latestSequencerBlock = (await sequencerProvider.getBlock(
'latest'
)) as any
await startReplica()
const matchingReplicaBlock = (await syncReplica(
latestSequencerBlock.number
)) as any
expect(matchingReplicaBlock.stateRoot).to.eq(
latestSequencerBlock.stateRoot
)
})
it('should sync ERC20 deployment and transfer', async () => {
ERC20 = await Factory__ERC20.deploy(
initialAmount,
tokenName,
tokenDecimals,
TokenSymbol
)
const transfer = await ERC20.transfer(other.address, 100)
await transfer.wait()
const latestSequencerBlock = (await provider.getBlock('latest')) as any
const matchingReplicaBlock = (await syncReplica(
latestSequencerBlock.number
)) as any
expect(matchingReplicaBlock.stateRoot).to.eq(
latestSequencerBlock.stateRoot
)
})
})
})
...@@ -8,6 +8,7 @@ type ServiceNames = ...@@ -8,6 +8,7 @@ type ServiceNames =
| 'l2geth' | 'l2geth'
| 'relayer' | 'relayer'
| 'verifier' | 'verifier'
| 'replica'
const OPS_DIRECTORY = path.join(process.cwd(), '../ops') const OPS_DIRECTORY = path.join(process.cwd(), '../ops')
const DEFAULT_SERVICES: ServiceNames[] = [ const DEFAULT_SERVICES: ServiceNames[] = [
......
...@@ -7,7 +7,7 @@ import { ...@@ -7,7 +7,7 @@ import {
getContractInterface, getContractInterface,
predeploys, predeploys,
} from '@eth-optimism/contracts' } from '@eth-optimism/contracts'
import { remove0x, Watcher } from '@eth-optimism/core-utils' import { injectL2Context, remove0x, Watcher } from '@eth-optimism/core-utils'
import { import {
Contract, Contract,
Wallet, Wallet,
...@@ -25,9 +25,11 @@ const env = cleanEnv(process.env, { ...@@ -25,9 +25,11 @@ const env = cleanEnv(process.env, {
L1_URL: str({ default: 'http://localhost:9545' }), L1_URL: str({ default: 'http://localhost:9545' }),
L2_URL: str({ default: 'http://localhost:8545' }), L2_URL: str({ default: 'http://localhost:8545' }),
VERIFIER_URL: str({ default: 'http://localhost:8547' }), VERIFIER_URL: str({ default: 'http://localhost:8547' }),
REPLICA_URL: str({ default: 'http://localhost:8549' }),
L1_POLLING_INTERVAL: num({ default: 10 }), L1_POLLING_INTERVAL: num({ default: 10 }),
L2_POLLING_INTERVAL: num({ default: 10 }), L2_POLLING_INTERVAL: num({ default: 10 }),
VERIFIER_POLLING_INTERVAL: num({ default: 10 }), VERIFIER_POLLING_INTERVAL: num({ default: 10 }),
REPLICA_POLLING_INTERVAL: num({ default: 10 }),
PRIVATE_KEY: str({ PRIVATE_KEY: str({
default: default:
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
...@@ -47,6 +49,9 @@ l2Provider.pollingInterval = env.L2_POLLING_INTERVAL ...@@ -47,6 +49,9 @@ l2Provider.pollingInterval = env.L2_POLLING_INTERVAL
export const verifierProvider = new providers.JsonRpcProvider(env.VERIFIER_URL) export const verifierProvider = new providers.JsonRpcProvider(env.VERIFIER_URL)
verifierProvider.pollingInterval = env.VERIFIER_POLLING_INTERVAL verifierProvider.pollingInterval = env.VERIFIER_POLLING_INTERVAL
export const replicaProvider = new providers.JsonRpcProvider(env.REPLICA_URL)
replicaProvider.pollingInterval = env.REPLICA_POLLING_INTERVAL
// The sequencer private key which is funded on L1 // The sequencer private key which is funded on L1
export const l1Wallet = new Wallet(env.PRIVATE_KEY, l1Provider) export const l1Wallet = new Wallet(env.PRIVATE_KEY, l1Provider)
...@@ -168,3 +173,18 @@ export const expectApprox = ( ...@@ -168,3 +173,18 @@ export const expectApprox = (
`Actual value is more than ${lowerDeviation}% less than target` `Actual value is more than ${lowerDeviation}% less than target`
).to.be.true ).to.be.true
} }
export const waitForL2Geth = async (
provider: providers.JsonRpcProvider
): Promise<providers.JsonRpcProvider> => {
let ready: boolean = false
while (!ready) {
try {
await provider.getNetwork()
ready = true
} catch (error) {
await sleep(1000)
}
}
return injectL2Context(provider)
}
...@@ -30,12 +30,14 @@ docker-compose \ ...@@ -30,12 +30,14 @@ docker-compose \
up --build --detach up --build --detach
``` ```
Optionally, run a verifier along the rest of the stack. Optionally, run a verifier along the rest of the stack. Run a replica with the same command by switching the service name!
``` ```
docker-compose up --scale verifier=1 \ docker-compose up --scale \
verifier=1 \
--build --detach --build --detach
``` ```
A Makefile has been provided for convience. The following targets are available. A Makefile has been provided for convience. The following targets are available.
- make up - make up
- make down - make down
......
...@@ -62,6 +62,7 @@ services: ...@@ -62,6 +62,7 @@ services:
# connect to the 2 layers # connect to the 2 layers
DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT: http://l1_chain:8545 DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT: http://l1_chain:8545
DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT: http://l2geth:8545 DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT: http://l2geth:8545
DATA_TRANSPORT_LAYER__SYNC_FROM_L2: 'true'
DATA_TRANSPORT_LAYER__L2_CHAIN_ID: 420 DATA_TRANSPORT_LAYER__L2_CHAIN_ID: 420
ports: ports:
- ${DTL_PORT:-7878}:7878 - ${DTL_PORT:-7878}:7878
...@@ -141,23 +142,46 @@ services: ...@@ -141,23 +142,46 @@ services:
build: build:
context: .. context: ..
dockerfile: ./ops/docker/Dockerfile.geth dockerfile: ./ops/docker/Dockerfile.geth
# override with the geth script and the env vars required for it
entrypoint: sh ./geth.sh entrypoint: sh ./geth.sh
env_file: env_file:
- ./envs/geth.env - ./envs/geth.env
environment: environment:
ETH1_HTTP: http://l1_chain:8545 ETH1_HTTP: http://l1_chain:8545
ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json
# used for getting the addresses
URL: http://deployer:8081/addresses.json URL: http://deployer:8081/addresses.json
# connecting to the DTL
ROLLUP_CLIENT_HTTP: http://dtl:7878 ROLLUP_CLIENT_HTTP: http://dtl:7878
ROLLUP_BACKEND: 'l1'
ETH1_CTC_DEPLOYMENT_HEIGHT: 8 ETH1_CTC_DEPLOYMENT_HEIGHT: 8
RETRIES: 60 RETRIES: 60
IS_VERIFIER: "true" ROLLUP_VERIFIER_ENABLE: 'true'
ports: ports:
- ${VERIFIER_HTTP_PORT:-8547}:8545 - ${VERIFIER_HTTP_PORT:-8547}:8545
- ${VERIFIER_WS_PORT:-8548}:8546 - ${VERIFIER_WS_PORT:-8548}:8546
replica:
depends_on:
- dtl
image: ethereumoptimism/l2geth
deploy:
replicas: 0
build:
context: ..
dockerfile: ./ops/docker/Dockerfile.geth
entrypoint: sh ./geth.sh
env_file:
- ./envs/geth.env
environment:
ETH1_HTTP: http://l1_chain:8545
ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json
URL: http://deployer:8081/addresses.json
ROLLUP_CLIENT_HTTP: http://dtl:7878
ROLLUP_BACKEND: 'l2'
ROLLUP_VERIFIER_ENABLE: 'true'
ETH1_CTC_DEPLOYMENT_HEIGHT: 8
RETRIES: 60
ports:
- ${L2GETH_HTTP_PORT:-8549}:8545
- ${L2GETH_WS_PORT:-8550}:8546
integration_tests: integration_tests:
image: ethereumoptimism/integration-tests image: ethereumoptimism/integration-tests
......
...@@ -17,6 +17,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common- ...@@ -17,6 +17,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common-
COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist
COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json
COPY --from=builder /optimism/packages/contracts/deployments ./packages/contracts/deployments
COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist
COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts
COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm
......
...@@ -18,6 +18,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common- ...@@ -18,6 +18,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common-
COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist
COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json
COPY --from=builder /optimism/packages/contracts/deployments ./packages/contracts/deployments
COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist
COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts
COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm
......
...@@ -18,6 +18,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common- ...@@ -18,6 +18,7 @@ COPY --from=builder /optimism/packages/common-ts/package.json ./packages/common-
COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist COPY --from=builder /optimism/packages/common-ts/dist ./packages/common-ts/dist
COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json COPY --from=builder /optimism/packages/contracts/package.json ./packages/contracts/package.json
COPY --from=builder /optimism/packages/contracts/deployments ./packages/contracts/deployments
COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist
COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts
COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./packages/contracts/artifacts-ovm
......
import { Signer, Contract, providers, ethers } from 'ethers'
import { Provider } from '@ethersproject/abstract-provider'
import { getL1ContractData, getL2ContractData } from './contract-data'
export type Network = 'goerli' | 'kovan' | 'mainnet'
interface L1Contracts {
addressManager: Contract
canonicalTransactionChain: Contract
executionManager: Contract
fraudVerifier: Contract
ethGateway: Contract
multiMessageRelayer: Contract
stateCommitmentChain: Contract
xDomainMessengerProxy: Contract
l1EthGatewayProxy: Contract
bondManager: Contract
}
interface L2Contracts {
eth: Contract
xDomainMessenger: Contract
messagePasser: Contract
messageSender: Contract
deployerWhiteList: Contract
ecdsaContractAccount: Contract
sequencerEntrypoint: Contract
erc1820Registry: Contract
addressManager: Contract
}
/**
* Validates user provided a singer or provider & throws error if not
*
* @param signerOrProvider
*/
const checkSignerType = (signerOrProvider: Signer | Provider) => {
if (!signerOrProvider) {
throw Error('signerOrProvider argument is undefined')
}
if (
!Provider.isProvider(signerOrProvider) &&
!Signer.isSigner(signerOrProvider)
) {
throw Error('signerOrProvider argument is the wrong type')
}
}
/**
* Connects a signer/provider to layer 1 contracts on a given network
*
* @param signerOrProvider ethers signer or provider
* @param network string denoting network
* @returns l1 contracts connected to signer/provider
*/
export const connectL1Contracts = async (
signerOrProvider: Signer | Provider,
network: Network
): Promise<L1Contracts> => {
checkSignerType(signerOrProvider)
if (!['mainnet', 'kovan', 'goerli'].includes(network)) {
throw Error('Must specify network: mainnet, kovan, or goerli.')
}
const l1ContractData = getL1ContractData(network)
const toEthersContract = (data) =>
new Contract(data.address, data.abi, signerOrProvider)
return {
addressManager: toEthersContract(l1ContractData.Lib_AddressManager),
canonicalTransactionChain: toEthersContract(
l1ContractData.OVM_CanonicalTransactionChain
),
executionManager: toEthersContract(l1ContractData.OVM_ExecutionManager),
fraudVerifier: toEthersContract(l1ContractData.OVM_FraudVerifier),
ethGateway: toEthersContract(l1ContractData.OVM_L1ETHGateway),
multiMessageRelayer: toEthersContract(
l1ContractData.OVM_L1MultiMessageRelayer
),
stateCommitmentChain: toEthersContract(
l1ContractData.OVM_StateCommitmentChain
),
xDomainMessengerProxy: toEthersContract(
l1ContractData.Proxy__OVM_L1CrossDomainMessenger
),
l1EthGatewayProxy: toEthersContract(l1ContractData.Proxy__OVM_L1ETHGateway),
// TODO: update this with actual bond manager when its ready
bondManager: toEthersContract(l1ContractData.mockOVM_BondManager),
}
}
/**
* Connects a signer/provider to layer 2 contracts (network agnostic)
*
* @param signerOrProvider ethers signer or provider
* @returns l2 contracts connected to signer/provider
*/
export const connectL2Contracts = async (
signerOrProvider
): Promise<L2Contracts> => {
const l2ContractData = await getL2ContractData()
checkSignerType(signerOrProvider)
const toEthersContract = (data) =>
new Contract(data.address, data.abi, signerOrProvider)
return {
eth: toEthersContract(l2ContractData.OVM_ETH),
xDomainMessenger: toEthersContract(
l2ContractData.OVM_L2CrossDomainMessenger
),
messagePasser: toEthersContract(l2ContractData.OVM_L2ToL1MessagePasser),
messageSender: toEthersContract(l2ContractData.OVM_L1MessageSender),
deployerWhiteList: toEthersContract(l2ContractData.OVM_DeployerWhitelist),
ecdsaContractAccount: toEthersContract(
l2ContractData.OVM_ECDSAContractAccount
),
sequencerEntrypoint: toEthersContract(
l2ContractData.OVM_SequencerEntrypoint
),
erc1820Registry: toEthersContract(l2ContractData.ERC1820Registry),
addressManager: toEthersContract(l2ContractData.Lib_AddressManager),
}
}
/* eslint-disable @typescript-eslint/no-var-requires */
import { predeploys as l2Addresses } from './predeploys'
import { Network } from './connect-contracts'
/**
* This file is necessarily not DRY because it needs to be usable
* in a browser context and can't take advantage of dynamic imports
* (ie: the json needs to all be imported when transpiled)
*/
const Mainnet__Lib_AddressManager = require('../deployments/mainnet/Lib_AddressManager.json')
const Mainnet__OVM_CanonicalTransactionChain = require('../deployments/mainnet/OVM_CanonicalTransactionChain.json')
const Mainnet__OVM_ExecutionManager = require('../deployments/mainnet/OVM_ExecutionManager.json')
const Mainnet__OVM_FraudVerifier = require('../deployments/mainnet/OVM_FraudVerifier.json')
const Mainnet__OVM_L1CrossDomainMessenger = require('../deployments/mainnet/OVM_L1CrossDomainMessenger.json')
const Mainnet__OVM_L1ETHGateway = require('../deployments/mainnet/OVM_L1ETHGateway.json')
const Mainnet__OVM_L1MultiMessageRelayer = require('../deployments/mainnet/OVM_L1MultiMessageRelayer.json')
const Mainnet__OVM_SafetyChecker = require('../deployments/mainnet/OVM_SafetyChecker.json')
const Mainnet__OVM_StateCommitmentChain = require('../deployments/mainnet/OVM_StateCommitmentChain.json')
const Mainnet__OVM_StateManagerFactory = require('../deployments/mainnet/OVM_StateManagerFactory.json')
const Mainnet__OVM_StateTransitionerFactory = require('../deployments/mainnet/OVM_StateTransitionerFactory.json')
const Mainnet__Proxy__OVM_L1CrossDomainMessenger = require('../deployments/mainnet/Proxy__OVM_L1CrossDomainMessenger.json')
const Mainnet__Proxy__OVM_L1ETHGateway = require('../deployments/mainnet/Proxy__OVM_L1ETHGateway.json')
const Mainnet__mockOVM_BondManager = require('../deployments/mainnet/mockOVM_BondManager.json')
const Kovan__Lib_AddressManager = require('../deployments/kovan/Lib_AddressManager.json')
const Kovan__OVM_CanonicalTransactionChain = require('../deployments/kovan/OVM_CanonicalTransactionChain.json')
const Kovan__OVM_ExecutionManager = require('../deployments/kovan/OVM_ExecutionManager.json')
const Kovan__OVM_FraudVerifier = require('../deployments/kovan/OVM_FraudVerifier.json')
const Kovan__OVM_L1CrossDomainMessenger = require('../deployments/kovan/OVM_L1CrossDomainMessenger.json')
const Kovan__OVM_L1ETHGateway = require('../deployments/kovan/OVM_L1ETHGateway.json')
const Kovan__OVM_L1MultiMessageRelayer = require('../deployments/kovan/OVM_L1MultiMessageRelayer.json')
const Kovan__OVM_SafetyChecker = require('../deployments/kovan/OVM_SafetyChecker.json')
const Kovan__OVM_StateCommitmentChain = require('../deployments/kovan/OVM_StateCommitmentChain.json')
const Kovan__OVM_StateManagerFactory = require('../deployments/kovan/OVM_StateManagerFactory.json')
const Kovan__OVM_StateTransitionerFactory = require('../deployments/kovan/OVM_StateTransitionerFactory.json')
const Kovan__Proxy__OVM_L1CrossDomainMessenger = require('../deployments/kovan/Proxy__OVM_L1CrossDomainMessenger.json')
const Kovan__Proxy__OVM_L1ETHGateway = require('../deployments/kovan/Proxy__OVM_L1ETHGateway.json')
const Kovan__mockOVM_BondManager = require('../deployments/kovan/mockOVM_BondManager.json')
const Goerli__Lib_AddressManager = require('../deployments/goerli/Lib_AddressManager.json')
const Goerli__OVM_CanonicalTransactionChain = require('../deployments/goerli/OVM_CanonicalTransactionChain.json')
const Goerli__OVM_ExecutionManager = require('../deployments/goerli/OVM_ExecutionManager.json')
const Goerli__OVM_FraudVerifier = require('../deployments/goerli/OVM_FraudVerifier.json')
const Goerli__OVM_L1CrossDomainMessenger = require('../deployments/goerli/OVM_L1CrossDomainMessenger.json')
const Goerli__OVM_L1ETHGateway = require('../deployments/goerli/OVM_L1ETHGateway.json')
const Goerli__OVM_L1MultiMessageRelayer = require('../deployments/goerli/OVM_L1MultiMessageRelayer.json')
const Goerli__OVM_SafetyChecker = require('../deployments/goerli/OVM_SafetyChecker.json')
const Goerli__OVM_StateCommitmentChain = require('../deployments/goerli/OVM_StateCommitmentChain.json')
const Goerli__OVM_StateManagerFactory = require('../deployments/goerli/OVM_StateManagerFactory.json')
const Goerli__OVM_StateTransitionerFactory = require('../deployments/goerli/OVM_StateTransitionerFactory.json')
const Goerli__Proxy__OVM_L1CrossDomainMessenger = require('../deployments/goerli/Proxy__OVM_L1CrossDomainMessenger.json')
const Goerli__Proxy__OVM_L1ETHGateway = require('../deployments/goerli/Proxy__OVM_L1ETHGateway.json')
const Goerli__mockOVM_BondManager = require('../deployments/goerli/mockOVM_BondManager.json')
export const getL1ContractData = (network: Network) => {
return {
Lib_AddressManager: {
mainnet: Mainnet__Lib_AddressManager,
kovan: Kovan__Lib_AddressManager,
goerli: Goerli__Lib_AddressManager,
}[network],
OVM_CanonicalTransactionChain: {
mainnet: Mainnet__OVM_CanonicalTransactionChain,
kovan: Kovan__OVM_CanonicalTransactionChain,
goerli: Goerli__OVM_CanonicalTransactionChain,
}[network],
OVM_ExecutionManager: {
mainnet: Mainnet__OVM_ExecutionManager,
kovan: Kovan__OVM_ExecutionManager,
goerli: Goerli__OVM_ExecutionManager,
}[network],
OVM_FraudVerifier: {
mainnet: Mainnet__OVM_FraudVerifier,
kovan: Kovan__OVM_FraudVerifier,
goerli: Goerli__OVM_FraudVerifier,
}[network],
OVM_L1CrossDomainMessenger: {
mainnet: Mainnet__OVM_L1CrossDomainMessenger,
kovan: Kovan__OVM_L1CrossDomainMessenger,
goerli: Goerli__OVM_L1CrossDomainMessenger,
}[network],
OVM_L1ETHGateway: {
mainnet: Mainnet__OVM_L1ETHGateway,
kovan: Kovan__OVM_L1ETHGateway,
goerli: Goerli__OVM_L1ETHGateway,
}[network],
OVM_L1MultiMessageRelayer: {
mainnet: Mainnet__OVM_L1MultiMessageRelayer,
kovan: Kovan__OVM_L1MultiMessageRelayer,
goerli: Goerli__OVM_L1MultiMessageRelayer,
}[network],
OVM_SafetyChecker: {
mainnet: Mainnet__OVM_SafetyChecker,
kovan: Kovan__OVM_SafetyChecker,
goerli: Goerli__OVM_SafetyChecker,
}[network],
OVM_StateCommitmentChain: {
mainnet: Mainnet__OVM_StateCommitmentChain,
kovan: Kovan__OVM_StateCommitmentChain,
goerli: Goerli__OVM_StateCommitmentChain,
}[network],
OVM_StateManagerFactory: {
mainnet: Mainnet__OVM_StateManagerFactory,
kovan: Kovan__OVM_StateManagerFactory,
goerli: Goerli__OVM_StateManagerFactory,
}[network],
OVM_StateTransitionerFactory: {
mainnet: Mainnet__OVM_StateTransitionerFactory,
kovan: Kovan__OVM_StateTransitionerFactory,
goerli: Goerli__OVM_StateTransitionerFactory,
}[network],
Proxy__OVM_L1CrossDomainMessenger: {
mainnet: Mainnet__Proxy__OVM_L1CrossDomainMessenger,
kovan: Kovan__Proxy__OVM_L1CrossDomainMessenger,
goerli: Goerli__Proxy__OVM_L1CrossDomainMessenger,
}[network],
Proxy__OVM_L1ETHGateway: {
mainnet: Mainnet__Proxy__OVM_L1ETHGateway,
kovan: Kovan__Proxy__OVM_L1ETHGateway,
goerli: Goerli__Proxy__OVM_L1ETHGateway,
}[network],
mockOVM_BondManager: {
mainnet: Mainnet__mockOVM_BondManager,
kovan: Kovan__mockOVM_BondManager,
goerli: Goerli__mockOVM_BondManager,
}[network],
}
}
const OVM_ETH = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/OVM_ETH.sol/OVM_ETH.json')
const OVM_L2CrossDomainMessenger = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L2CrossDomainMessenger.sol/OVM_L2CrossDomainMessenger.json')
const OVM_L2ToL1MessagePasser = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/OVM_L2ToL1MessagePasser.sol/OVM_L2ToL1MessagePasser.json')
const OVM_L1MessageSender = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/OVM_L1MessageSender.sol/OVM_L1MessageSender.json')
const OVM_DeployerWhitelist = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/OVM_DeployerWhitelist.sol/OVM_DeployerWhitelist.json')
const OVM_ECDSAContractAccount = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/accounts/OVM_ECDSAContractAccount.sol/OVM_ECDSAContractAccount.json')
const OVM_SequencerEntrypoint = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/OVM_SequencerEntrypoint.sol/OVM_SequencerEntrypoint.json')
const ERC1820Registry = require('../artifacts-ovm/contracts/optimistic-ethereum/OVM/predeploys/ERC1820Registry.sol/ERC1820Registry.json')
const Lib_AddressManager = require('../artifacts-ovm/contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol/Lib_AddressManager.json')
export const getL2ContractData = () => {
return {
OVM_ETH: {
abi: OVM_ETH.abi,
address: l2Addresses.OVM_ETH,
},
OVM_L2CrossDomainMessenger: {
abi: OVM_L2CrossDomainMessenger.abi,
address: l2Addresses.OVM_L2CrossDomainMessenger,
},
OVM_L2ToL1MessagePasser: {
abi: OVM_L2ToL1MessagePasser.abi,
address: l2Addresses.OVM_L2ToL1MessagePasser,
},
OVM_L1MessageSender: {
abi: OVM_L1MessageSender.abi,
address: l2Addresses.OVM_L1MessageSender,
},
OVM_DeployerWhitelist: {
abi: OVM_DeployerWhitelist.abi,
address: l2Addresses.OVM_DeployerWhitelist,
},
OVM_ECDSAContractAccount: {
abi: OVM_ECDSAContractAccount.abi,
address: l2Addresses.OVM_ECDSAContractAccount,
},
OVM_SequencerEntrypoint: {
abi: OVM_SequencerEntrypoint.abi,
address: l2Addresses.OVM_SequencerEntrypoint,
},
ERC1820Registry: {
abi: ERC1820Registry.abi,
address: l2Addresses.ERC1820Registry,
},
Lib_AddressManager: {
abi: Lib_AddressManager.abi,
address: l2Addresses.Lib_AddressManager,
},
}
}
...@@ -2,3 +2,4 @@ export * from './contract-defs' ...@@ -2,3 +2,4 @@ export * from './contract-defs'
export * from './state-dump/get-dump' export * from './state-dump/get-dump'
export * from './contract-deployment' export * from './contract-deployment'
export * from './predeploys' export * from './predeploys'
export * from './connect-contracts'
import { ethers } from 'hardhat'
import { Signer, Contract } from 'ethers'
import {
connectL1Contracts,
connectL2Contracts,
} from '../dist/connect-contracts'
import { expect } from './setup'
describe('connectL1Contracts', () => {
let user: Signer
const l1ContractNames = [
'addressManager',
'canonicalTransactionChain',
'executionManager',
'fraudVerifier',
'ethGateway',
'multiMessageRelayer',
'stateCommitmentChain',
'xDomainMessengerProxy',
'l1EthGatewayProxy',
'bondManager',
]
const l2ContractNames = [
'eth',
'xDomainMessenger',
'messagePasser',
'messageSender',
'deployerWhiteList',
'ecdsaContractAccount',
'sequencerEntrypoint',
'erc1820Registry',
'addressManager',
]
before(async () => {
;[user] = await ethers.getSigners()
})
it(`connectL1Contracts should throw error if signer or provider isn't provided.`, async () => {
try {
await connectL1Contracts(undefined, 'mainnet')
} catch (err) {
expect(err.message).to.be.equal('signerOrProvider argument is undefined')
}
})
for (const name of l1ContractNames) {
it(`connectL1Contracts should return a contract assigned to a field named "${name}"`, async () => {
const l1Contracts = await connectL1Contracts(user, 'mainnet')
expect(l1Contracts[name]).to.be.an.instanceOf(Contract)
})
}
for (const name of l2ContractNames) {
it(`connectL2Contracts should return a contract assigned to a field named "${name}"`, async () => {
const l2Contracts = await connectL2Contracts(user)
expect(l2Contracts[name]).to.be.an.instanceOf(Contract)
})
}
})
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"resolveJsonModule": true "resolveJsonModule": true,
} }
} }
...@@ -88,7 +88,11 @@ export class L2IngestionService extends BaseService<L2IngestionServiceOptions> { ...@@ -88,7 +88,11 @@ export class L2IngestionService extends BaseService<L2IngestionServiceOptions> {
) )
// We're already at the head, so no point in attempting to sync. // We're already at the head, so no point in attempting to sync.
if (highestSyncedL2BlockNumber === targetL2Block) { // Also wait on edge case of no L2 transactions
if (
highestSyncedL2BlockNumber === targetL2Block ||
currentL2Block === 0
) {
await sleep(this.options.pollingInterval) await sleep(this.options.pollingInterval)
continue continue
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
"files": [ "files": [
"dist/index" "dist/*"
], ],
"scripts": { "scripts": {
"start": "node ./exec/run-message-relayer.js", "start": "node ./exec/run-message-relayer.js",
......
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