Commit 6c685d5f authored by Mark Tyneway's avatar Mark Tyneway

integration-tests-bedrock: clean up package

Also lint now that linting rules apply
parent f71b40e7
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"lint:fix": "yarn lint:check --fix", "lint:fix": "yarn lint:check --fix",
"lint:check": "eslint . --max-warnings=0", "lint:check": "eslint . --max-warnings=0",
"build:contracts": "forge build --root . -c contracts -o artifacts", "build:contracts": "forge build --root . -c contracts -o artifacts",
"test": "ts-mocha --timeout 30000 test/**/*.spec.ts", "test": "echo 'no unit tests'",
"test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts", "test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts",
"test:integration:live": "NO_NETWORK=true IS_LIVE_NETWORK=true hardhat --network optimism test", "test:integration:live": "NO_NETWORK=true IS_LIVE_NETWORK=true hardhat --network optimism test",
"clean": "rimraf cache artifacts" "clean": "rimraf cache artifacts"
...@@ -31,40 +31,17 @@ ...@@ -31,40 +31,17 @@
"@eth-optimism/core-utils": "0.8.5", "@eth-optimism/core-utils": "0.8.5",
"@eth-optimism/sdk": "1.1.6", "@eth-optimism/sdk": "1.1.6",
"@ethersproject/abstract-provider": "^5.6.1", "@ethersproject/abstract-provider": "^5.6.1",
"@ethersproject/providers": "^5.6.8",
"@ethersproject/transactions": "^5.6.2",
"@types/chai": "^4.2.18",
"@types/chai-as-promised": "^7.1.4",
"@types/mocha": "^8.2.2",
"@types/rimraf": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"async-mutex": "^0.3.2",
"babel-eslint": "^10.1.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"commander": "^8.3.0", "chai": "^4.3.4",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"envalid": "^7.1.0", "envalid": "^7.1.0",
"eslint": "^7.27.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jsdoc": "^35.1.2",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-unicorn": "^32.0.1",
"ethereum-waffle": "^3.3.0", "ethereum-waffle": "^3.3.0",
"ethers": "^5.6.8", "ethers": "^5.6.8",
"mocha": "^8.4.0",
"node-fetch": "^2.6.7",
"prom-client": "^14.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ts-node": "^10.7.0", "ts-node": "^10.7.0"
"typescript": "^4.3.5"
}, },
"dependencies": { "dependencies": {
"ts-mocha": "^9.0.2", "rlp": "^3.0.0",
"winston": "^3.7.2" "winston": "^3.7.2"
} }
} }
...@@ -2,30 +2,41 @@ ...@@ -2,30 +2,41 @@
// can fall behind. // can fall behind.
/* Imports: External */ /* Imports: External */
import { BigNumber, constants, Contract, ContractReceipt, utils, Wallet } from 'ethers' import {
BigNumber,
constants,
Contract,
ContractReceipt,
utils,
Wallet,
} from 'ethers'
import { awaitCondition } from '@eth-optimism/core-utils' import { awaitCondition } from '@eth-optimism/core-utils'
import * as rlp from 'rlp' import * as rlp from 'rlp'
import { Block } from '@ethersproject/abstract-provider' import { Block } from '@ethersproject/abstract-provider'
/* Imports: Internal */
import env from './shared/env'
import { expect } from './shared/setup'
import winston from 'winston' import winston from 'winston'
import { predeploys } from '@eth-optimism/contracts' import { predeploys } from '@eth-optimism/contracts'
const l2ToL1MessagePasserArtifact = require('../../contracts/artifacts/contracts/L2/L2ToL1MessagePasser.sol/L2ToL1MessagePasser.json') import env from './shared/env'
const l2OOracleArtifact = require('../../contracts/artifacts/contracts/L1/L2OutputOracle.sol/L2OutputOracle.json') import { expect } from './shared/setup'
import l2ToL1MessagePasserArtifact from '../../contracts-bedrock/artifacts/contracts/L2/L2ToL1MessagePasser.sol/L2ToL1MessagePasser.json'
import l2OOracleArtifact from '../../contracts-bedrock/artifacts/contracts/L1/L2OutputOracle.sol/L2OutputOracle.json'
/** /**
* Calculates the target output timestamp to make the withdrawal proof against. ie. the first * Calculates the target output timestamp to make the withdrawal proof against. ie. the first
* output with a timestamp greater than the burn block timestamp. * output with a timestamp greater than the burn block timestamp.
*
* @param {Contract} oracle Address of the L2 Output Oracle. * @param {Contract} oracle Address of the L2 Output Oracle.
* @param {number} withdrawalTimestamp L2 timestamp of the block the withdrawal was made in. * @param {number} withdrawalTimestamp L2 timestamp of the block the withdrawal was made in.
*/ */
const getTargetOutput = async (oracle: Contract, withdrawalTimestamp: number) => { const getTargetOutput = async (
oracle: Contract,
withdrawalTimestamp: number
) => {
const submissionInterval = (await oracle.SUBMISSION_INTERVAL()).toNumber() const submissionInterval = (await oracle.SUBMISSION_INTERVAL()).toNumber()
const startingBlockTimestamp = (await oracle.STARTING_BLOCK_TIMESTAMP()).toNumber() const startingBlockTimestamp = (
let nextTimestamp = (await oracle.nextTimestamp()).toNumber() await oracle.STARTING_BLOCK_TIMESTAMP()
).toNumber()
const nextTimestamp = (await oracle.nextTimestamp()).toNumber()
let targetOutputTimestamp let targetOutputTimestamp
if (withdrawalTimestamp < nextTimestamp) { if (withdrawalTimestamp < nextTimestamp) {
// Just use the next timestamp // Just use the next timestamp
...@@ -33,18 +44,16 @@ const getTargetOutput = async (oracle: Contract, withdrawalTimestamp: number) => ...@@ -33,18 +44,16 @@ const getTargetOutput = async (oracle: Contract, withdrawalTimestamp: number) =>
} else { } else {
// Calculate the first timestamp greater than the burnBlock which will be appended. // Calculate the first timestamp greater than the burnBlock which will be appended.
targetOutputTimestamp = targetOutputTimestamp =
Math.ceil( Math.ceil(
(withdrawalTimestamp - startingBlockTimestamp) (withdrawalTimestamp - startingBlockTimestamp) / submissionInterval
/ submissionInterval ) *
) submissionInterval +
* submissionInterval startingBlockTimestamp
+ startingBlockTimestamp
} }
return targetOutputTimestamp return targetOutputTimestamp
} }
describe('Withdrawals', () => { describe('Withdrawals', () => {
let logger: winston.Logger let logger: winston.Logger
let portal: Contract let portal: Contract
...@@ -58,7 +67,7 @@ describe('Withdrawals', () => { ...@@ -58,7 +67,7 @@ describe('Withdrawals', () => {
withdrawer = new Contract( withdrawer = new Contract(
predeploys.OVM_L2ToL1MessagePasser, predeploys.OVM_L2ToL1MessagePasser,
l2ToL1MessagePasserArtifact.abi, l2ToL1MessagePasserArtifact.abi
) )
}) })
...@@ -78,16 +87,18 @@ describe('Withdrawals', () => { ...@@ -78,16 +87,18 @@ describe('Withdrawals', () => {
recipient: recipient.address, recipient: recipient.address,
}) })
logger.info('Depositing to new address on L2') logger.info('Depositing to new address on L2')
let tx = await portal.connect(env.l1Wallet).depositTransaction( let tx = await portal
recipient.address, .connect(env.l1Wallet)
utils.parseEther('1.337'), .depositTransaction(
gasLimit, recipient.address,
false, utils.parseEther('1.337'),
[], gasLimit,
{ false,
value: utils.parseEther('1.337'), [],
}, {
) value: utils.parseEther('1.337'),
}
)
await tx.wait() await tx.wait()
await awaitCondition(async () => { await awaitCondition(async () => {
...@@ -111,7 +122,7 @@ describe('Withdrawals', () => { ...@@ -111,7 +122,7 @@ describe('Withdrawals', () => {
[], [],
{ {
value, value,
}, }
) )
const receipt: ContractReceipt = await tx.wait() const receipt: ContractReceipt = await tx.wait()
expect(receipt.events!.length).to.eq(1) expect(receipt.events!.length).to.eq(1)
...@@ -135,8 +146,8 @@ describe('Withdrawals', () => { ...@@ -135,8 +146,8 @@ describe('Withdrawals', () => {
value, value,
gasLimit, gasLimit,
'0x', '0x',
], ]
), )
) )
const included = await withdrawer.sentMessages(withdrawalHash) const included = await withdrawer.sentMessages(withdrawalHash)
...@@ -150,39 +161,52 @@ describe('Withdrawals', () => { ...@@ -150,39 +161,52 @@ describe('Withdrawals', () => {
portal = portal.connect(recipient) portal = portal.connect(recipient)
const oracle = new Contract( const oracle = new Contract(
await portal.L2_ORACLE(), await portal.L2_ORACLE(),
l2OOracleArtifact.abi, l2OOracleArtifact.abi
).connect(recipient) ).connect(recipient)
const targetOutputTimestamp = await getTargetOutput(oracle, burnBlock.timestamp) const targetOutputTimestamp = await getTargetOutput(
oracle,
burnBlock.timestamp
)
// Set the timeout based on the diff between latest output and target output timestamp. // Set the timeout based on the diff between latest output and target output timestamp.
let latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() let latestBlockTimestamp = (
await oracle.latestBlockTimestamp()
).toNumber()
let difference = targetOutputTimestamp - latestBlockTimestamp let difference = targetOutputTimestamp - latestBlockTimestamp
this.timeout(difference * 5000) this.timeout(difference * 5000)
let output: string let output: string
await awaitCondition(async () => { await awaitCondition(
const proposal = await oracle.getL2Output(targetOutputTimestamp) async () => {
output = proposal.outputRoot const proposal = await oracle.getL2Output(targetOutputTimestamp)
latestBlockTimestamp = (await oracle.latestBlockTimestamp()).toNumber() output = proposal.outputRoot
if(targetOutputTimestamp - latestBlockTimestamp < difference){ latestBlockTimestamp = (
// Only log when a new output has been appended await oracle.latestBlockTimestamp()
difference = targetOutputTimestamp - latestBlockTimestamp ).toNumber()
logger.info('Waiting for output submission', { if (targetOutputTimestamp - latestBlockTimestamp < difference) {
targetTimestamp: targetOutputTimestamp, // Only log when a new output has been appended
latestOracleTS: latestBlockTimestamp, difference = targetOutputTimestamp - latestBlockTimestamp
difference, logger.info('Waiting for output submission', {
output, targetTimestamp: targetOutputTimestamp,
}) latestOracleTS: latestBlockTimestamp,
} difference,
return output != constants.HashZero output,
}, 2000, 2*difference) })
}
return output !== constants.HashZero
},
2000,
2 * difference
)
// suppress compilation errors since Typescript cannot detect // suppress compilation errors since Typescript cannot detect
// that awaitCondition above will throw if it times out. // that awaitCondition above will throw if it times out.
output = output! output = output!
const blocksSinceBurn = Math.floor((targetOutputTimestamp - burnBlock.timestamp) / 2) const blocksSinceBurn = Math.floor(
(targetOutputTimestamp - burnBlock.timestamp) / 2
)
const targetBlockNum = burnBlock.number + blocksSinceBurn + 1 const targetBlockNum = burnBlock.number + blocksSinceBurn + 1
const targetBlockNumHex = utils.hexValue(targetBlockNum) const targetBlockNumHex = utils.hexValue(targetBlockNum)
const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract const storageSlot = '00'.repeat(31) + '01' // i.e the second variable declared in the contract
...@@ -192,19 +216,19 @@ describe('Withdrawals', () => { ...@@ -192,19 +216,19 @@ describe('Withdrawals', () => {
targetBlockNumHex, targetBlockNumHex,
]) ])
const {stateRoot: targetStateRoot, hash: targetHash} = await env.l2Provider.send( const { stateRoot: targetStateRoot, hash: targetHash } =
'eth_getBlockByNumber', await env.l2Provider.send('eth_getBlockByNumber', [
[
targetBlockNumHex, targetBlockNumHex,
false, false,
], ])
)
const finalizationPeriod = (await portal.FINALIZATION_PERIOD()).toNumber() const finalizationPeriod = (await portal.FINALIZATION_PERIOD()).toNumber()
logger.info('Waiting finalization period', { logger.info('Waiting finalization period', {
seconds: finalizationPeriod, seconds: finalizationPeriod,
}) })
await new Promise((resolve) => setTimeout(resolve, finalizationPeriod * 1000)) await new Promise((resolve) =>
setTimeout(resolve, finalizationPeriod * 1000)
)
logger.info('Finalizing withdrawal') logger.info('Finalizing withdrawal')
const initialBal = await recipient.getBalance() const initialBal = await recipient.getBalance()
...@@ -225,7 +249,7 @@ describe('Withdrawals', () => { ...@@ -225,7 +249,7 @@ describe('Withdrawals', () => {
rlp.encode(proof.storageProof[0].proof), rlp.encode(proof.storageProof[0].proof),
{ {
gasLimit, gasLimit,
}, }
) )
await tx.wait() await tx.wait()
const finalBal = await recipient.getBalance() const finalBal = await recipient.getBalance()
......
...@@ -5,9 +5,8 @@ import { awaitCondition } from '@eth-optimism/core-utils' ...@@ -5,9 +5,8 @@ import { awaitCondition } from '@eth-optimism/core-utils'
/* Imports: Internal */ /* Imports: Internal */
import { defaultTransactionFactory } from './shared/utils' import { defaultTransactionFactory } from './shared/utils'
import env from './shared/env' import env from './shared/env'
import counterArtifact from '../artifacts/Counter.sol/Counter.json'
const counterArtifact = require('../artifacts/Counter.sol/Counter.json') import multiDepositorArtifact from '../artifacts/MultiDepositor.sol/MultiDepositor.json'
const multiDepositorArtifact = require('../artifacts/MultiDepositor.sol/MultiDepositor.json')
describe('Deposits', () => { describe('Deposits', () => {
let portal: Contract let portal: Contract
...@@ -29,7 +28,7 @@ describe('Deposits', () => { ...@@ -29,7 +28,7 @@ describe('Deposits', () => {
[], [],
{ {
value: tx.value, value: tx.value,
}, }
) )
await result.wait() await result.wait()
...@@ -44,7 +43,7 @@ describe('Deposits', () => { ...@@ -44,7 +43,7 @@ describe('Deposits', () => {
const value = utils.parseEther('0.1') const value = utils.parseEther('0.1')
const factory = new ContractFactory( const factory = new ContractFactory(
multiDepositorArtifact.abi, multiDepositorArtifact.abi,
multiDepositorArtifact.bytecode.object, multiDepositorArtifact.bytecode.object
).connect(env.l1Wallet) ).connect(env.l1Wallet)
const contract = await factory.deploy(portal.address) const contract = await factory.deploy(portal.address)
await contract.deployed() await contract.deployed()
...@@ -63,7 +62,7 @@ describe('Deposits', () => { ...@@ -63,7 +62,7 @@ describe('Deposits', () => {
const value = utils.parseEther('0.1') const value = utils.parseEther('0.1')
const factory = new ContractFactory( const factory = new ContractFactory(
counterArtifact.abi, counterArtifact.abi,
counterArtifact.bytecode.object, counterArtifact.bytecode.object
) )
const tx = await factory.getDeployTransaction() const tx = await factory.getDeployTransaction()
const result = await portal.depositTransaction( const result = await portal.depositTransaction(
...@@ -73,8 +72,8 @@ describe('Deposits', () => { ...@@ -73,8 +72,8 @@ describe('Deposits', () => {
true, true,
tx.data, tx.data,
{ {
value: value, value,
}, }
) )
await result.wait() await result.wait()
const l2Nonce = await env.l2Wallet.getTransactionCount() const l2Nonce = await env.l2Wallet.getTransactionCount()
......
...@@ -5,8 +5,7 @@ import { ContractFactory, Wallet } from 'ethers' ...@@ -5,8 +5,7 @@ import { ContractFactory, Wallet } from 'ethers'
import { expect } from './shared/setup' import { expect } from './shared/setup'
import { defaultTransactionFactory } from './shared/utils' import { defaultTransactionFactory } from './shared/utils'
import env from './shared/env' import env from './shared/env'
import counterArtifact from '../artifacts/Counter.sol/Counter.json'
const counterArtifact = require('../artifacts/Counter.sol/Counter.json')
describe('RPCs', () => { describe('RPCs', () => {
let wallet: Wallet let wallet: Wallet
...@@ -38,10 +37,10 @@ describe('RPCs', () => { ...@@ -38,10 +37,10 @@ describe('RPCs', () => {
it('should correctly process a contract creation', async () => { it('should correctly process a contract creation', async () => {
const factory = new ContractFactory( const factory = new ContractFactory(
counterArtifact.abi, counterArtifact.abi,
counterArtifact.bytecode.object, counterArtifact.bytecode.object
).connect(wallet) ).connect(wallet)
const counter = await factory.deploy({ const counter = await factory.deploy({
gasLimit: 1_000_000 gasLimit: 1_000_000,
}) })
await counter.deployed() await counter.deployed()
expect(await env.l2Provider.getCode(counter.address)).not.to.equal('0x') expect(await env.l2Provider.getCode(counter.address)).not.to.equal('0x')
......
...@@ -2,27 +2,26 @@ ...@@ -2,27 +2,26 @@
import { Wallet, providers, Contract } from 'ethers' import { Wallet, providers, Contract } from 'ethers'
import { bool, cleanEnv, num, str } from 'envalid' import { bool, cleanEnv, num, str } from 'envalid'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import winston, { info } from 'winston' import winston from 'winston'
const {combine, timestamp, printf, colorize, align} = winston.format const { combine, timestamp, printf, colorize, align } = winston.format
/* Imports: Internal */ /* Imports: Internal */
const portalArtifact = require('../../../contracts/artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json') import portalArtifact from '../../../contracts-bedrock/artifacts/contracts/L1/OptimismPortal.sol/OptimismPortal.json'
dotenv.config() dotenv.config()
const procEnv = cleanEnv(process.env, { const procEnv = cleanEnv(process.env, {
L1_URL: str({default: 'http://localhost:8545'}), L1_URL: str({ default: 'http://localhost:8545' }),
L1_POLLING_INTERVAL: num({default: 10}), L1_POLLING_INTERVAL: num({ default: 10 }),
L2_URL: str({default: 'http://localhost:9545'}), L2_URL: str({ default: 'http://localhost:9545' }),
L2_POLLING_INTERVAL: num({default: 1}), L2_POLLING_INTERVAL: num({ default: 1 }),
OPTIMISM_PORTAL_ADDRESS: str(), OPTIMISM_PORTAL_ADDRESS: str(),
PRIVATE_KEY: str({ PRIVATE_KEY: str({
default: default: 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
}), }),
MOCHA_TIMEOUT: num({ MOCHA_TIMEOUT: num({
...@@ -72,13 +71,13 @@ export class OptimismEnv { ...@@ -72,13 +71,13 @@ export class OptimismEnv {
this.l2Provider = l2Provider this.l2Provider = l2Provider
this.optimismPortal = new Contract( this.optimismPortal = new Contract(
procEnv.OPTIMISM_PORTAL_ADDRESS, procEnv.OPTIMISM_PORTAL_ADDRESS,
portalArtifact.abi, portalArtifact.abi
) )
this.logger = winston.createLogger({ this.logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info', level: process.env.LOG_LEVEL || 'info',
format: combine( format: combine(
{ {
transform(info) { transform: (info) => {
// @ts-ignore // @ts-ignore
const args = info[Symbol.for('splat')] const args = info[Symbol.for('splat')]
const meta = args ? args[0] : null const meta = args ? args[0] : null
...@@ -87,16 +86,18 @@ export class OptimismEnv { ...@@ -87,16 +86,18 @@ export class OptimismEnv {
return info return info
}, },
}, },
colorize({all: true}), colorize({ all: true }),
timestamp({ timestamp({
format: 'YYYY-MM-DD hh:mm:ss.SSS A', format: 'YYYY-MM-DD hh:mm:ss.SSS A',
}), }),
align(), align(),
printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`), printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`)
), ),
transports: [new winston.transports.Stream({ transports: [
stream: process.stderr, new winston.transports.Stream({
})], stream: process.stderr,
}),
],
}) })
} }
} }
......
...@@ -7,4 +7,4 @@ chai.use(solidity) ...@@ -7,4 +7,4 @@ chai.use(solidity)
chai.use(chaiAsPromised) chai.use(chaiAsPromised)
const expect = chai.expect const expect = chai.expect
export { expect } export { expect }
\ No newline at end of file
...@@ -8,4 +8,3 @@ export const defaultTransactionFactory = () => { ...@@ -8,4 +8,3 @@ export const defaultTransactionFactory = () => {
value: BigNumber.from(0), value: BigNumber.from(0),
} }
} }
{ {
"extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"target": "es2018", "outDir": "./dist"
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "dist",
"declaration": true,
"resolveJsonModule": true
}, },
"include": [ "include": [
"src/**/*",
"./test", "./test",
"./artifacts/**/*.json", "./artifacts/**/*.json",
"./tasks/**/*.ts", "./tasks/**/*.ts",
......
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