diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index cf63567842c9c..939301f04501f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -20,9 +20,6 @@ jobs: - 5000:5000 strategy: matrix: - batch-submitter: - - ts-batch-submitter - - go-batch-submitter batch-type: - zlib - legacy @@ -53,7 +50,7 @@ jobs: working-directory: ./ops run: | ./scripts/stats.sh & - docker-compose -f docker-compose.yml -f docker-compose.${{ matrix.batch-submitter }}.yml up -d + docker-compose -f docker-compose.yml up -d - name: Wait for the Sequencer node working-directory: ./ops diff --git a/.github/workflows/ts-packages.yml b/.github/workflows/ts-packages.yml index 8968fcb73999f..4cc40266ce455 100644 --- a/.github/workflows/ts-packages.yml +++ b/.github/workflows/ts-packages.yml @@ -113,12 +113,6 @@ jobs: fail_ci_if_error: false verbose: true flags: core-utils - - uses: codecov/codecov-action@v1 - with: - files: ./packages/batch-submitter/coverage.json - fail_ci_if_error: false - verbose: true - flags: batch-submitter - uses: codecov/codecov-action@v1 with: files: ./packages/data-transport-layer/coverage.json @@ -170,10 +164,6 @@ jobs: # if: steps.yarn-cache.outputs.cache-hit != 'true' run: yarn install - - name: Check packages/batch-submitter - working-directory: ./packages/batch-submitter - run: npx depcheck - - name: Check packages/contracts working-directory: ./packages/contracts run: npx depcheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0413bff6c1231..5485a08be4d99 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -116,7 +116,7 @@ This will build the following containers: * [`l2geth`](https://hub.docker.com/r/ethereumoptimism/l2geth): L2 geth node running in Sequencer mode * [`verifier`](https://hub.docker.com/r/ethereumoptimism/go-ethereum): L2 geth node running in Verifier mode * [`relayer`](https://hub.docker.com/r/ethereumoptimism/message-relayer): helper process that relays messages between L1 and L2 -* [`batch_submitter`](https://hub.docker.com/r/ethereumoptimism/batch-submitter): service that submits batches of Sequencer transactions to the L1 chain +* [`batch_submitter`](https://hub.docker.com/r/ethereumoptimism/batch-submitter-service): service that submits batches of Sequencer transactions to the L1 chain * [`integration_tests`](https://hub.docker.com/r/ethereumoptimism/integration-tests): integration tests in a box If you want to make a change to a container, you'll need to take it down and rebuild it. diff --git a/README.md b/README.md index 7c47621536388..d899873cc62c4 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ root │ ├── core-utils: Low-level utilities that make building Optimism easier │ ├── common-ts: Common tools for building apps in TypeScript │ ├── data-transport-layer: Service for indexing Optimism-related L1 data -│ ├── batch-submitter: Service for submitting batches of transactions and results to L1 │ ├── message-relayer: Tool for automatically relaying L1<>L2 messages in development │ └── replica-healthcheck: Service for monitoring the health of a replica node ├── go diff --git a/ops/Makefile b/ops/Makefile index 4d4dd82503f37..7ff3285bd1b04 100644 --- a/ops/Makefile +++ b/ops/Makefile @@ -1,7 +1,5 @@ -BATCH_SUBMITTER ?= docker-compose.ts-batch-submitter.yml DOCKER_COMPOSE_CMD := docker-compose \ - -f docker-compose.yml \ - -f $(BATCH_SUBMITTER) + -f docker-compose.yml build: DOCKER_BUILDKIT=1 \ diff --git a/ops/README.md b/ops/README.md index 90c175577d057..d3b46276d6259 100644 --- a/ops/README.md +++ b/ops/README.md @@ -26,7 +26,6 @@ The base stack can be started and stopped with a command like this: ``` docker-compose \ -f docker-compose.yml \ - -f docker-compose.ts-batch-submitter.yml \ up --build --detach ``` @@ -40,7 +39,6 @@ To start the stack with monitoring enabled, just add the metric composition file ``` docker-compose \ -f docker-compose.yml \ - -f docker-compose.ts-batch-submitter.yml \ -f docker-compose-metrics.yml \ up --build --detach ``` @@ -50,7 +48,6 @@ Optionally, run a verifier along the rest of the stack. Run a replica with the s ``` docker-compose -f docker-compose.yml \ - -f docker-compose.ts-batch-submitter.yml \ up --scale \ verifier=1 \ --build --detach @@ -71,24 +68,6 @@ Fees can be turned off at runtime by setting the environment variable ROLLUP_ENFORCE_FEES=false docker-compose up ``` -## Using the Go Batch Submitter - -The existing Typescript batch submitter is in the process of being reimplemented -in Go. During this transition, the user is required to specify which batch -submitter to use with docker-compose. - -The commands above all use the Typescript batch submitter, by specifying -`-f docker-compose.ts-batch-submitter.yml`. This can be swapped out for the go -batch submitter by supplying `-f docker-compose.go-batch-submitter.yml` instead. - -Additionally, the `make` targets assume the use of the Typescript batch -submitter. This can be overridden by setting the `BATCH_SUBMITTER` environment -variable, e.g. `BATCH_SUBMITTER=docker-compose.go-batch-submitter.yml make up`. - -Once the transition is complete, specifying the desired batch submitter will be -obsolete, and the Go batch submitter will be selected by default from the -`docker-compose.yml` file and `Makefile`. - ## Cross domain communication By default, the `message-relayer` service is turned off. This means that diff --git a/ops/docker-compose-nobuild.yml b/ops/docker-compose-nobuild.yml index 128d706706c4c..3988f589fda4f 100644 --- a/ops/docker-compose-nobuild.yml +++ b/ops/docker-compose-nobuild.yml @@ -85,16 +85,17 @@ services: - l1_chain - deployer - l2geth - image: ethereumoptimism/batch-submitter:${DOCKER_TAG:-prerelease-0.5.0-rc-7-ee217ce} - entrypoint: ./batches.sh + image: ethereumoptimism/batch-submitter-service:${DOCKER_TAG:-prerelease-0.5.0-rc-7-ee217ce} + entrypoint: ./batch-submitter.sh env_file: - - ./envs/batches.env + - ./envs/batch-submitter.env environment: - L1_NODE_WEB3_URL: http://l1_chain:8545 - L2_NODE_WEB3_URL: http://l2geth:8545 - URL: http://deployer:8081/addresses.json - SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" - PROPOSER_PRIVATE_KEY: "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" + L1_ETH_RPC: http://l1_chain:8545 + L2_ETH_RPC: http://l2geth:8545 + URL: http://deployer:8081/addresses.json + BATCH_SUBMITTER_SEQUENCER_PRIVATE_KEY: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d' + BATCH_SUBMITTER_PROPOSER_PRIVATE_KEY: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a' + BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE: ${BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE:-zlib} verifier: depends_on: diff --git a/ops/docker-compose.go-batch-submitter.yml b/ops/docker-compose.go-batch-submitter.yml deleted file mode 100644 index ea8f5dfd664c2..0000000000000 --- a/ops/docker-compose.go-batch-submitter.yml +++ /dev/null @@ -1,19 +0,0 @@ -services: - batch_submitter: - depends_on: - - l1_chain - - deployer - - l2geth - build: - context: .. - dockerfile: ./ops/docker/Dockerfile.batch-submitter-service - entrypoint: ./batch-submitter.sh - env_file: - - ./envs/batch-submitter.env - environment: - L1_ETH_RPC: http://l1_chain:8545 - L2_ETH_RPC: http://l2geth:8545 - URL: http://deployer:8081/addresses.json - BATCH_SUBMITTER_SEQUENCER_PRIVATE_KEY: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d' - BATCH_SUBMITTER_PROPOSER_PRIVATE_KEY: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a' - BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE: ${BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE:-zlib} diff --git a/ops/docker-compose.ts-batch-submitter.yml b/ops/docker-compose.ts-batch-submitter.yml deleted file mode 100644 index da0b3b7e9c477..0000000000000 --- a/ops/docker-compose.ts-batch-submitter.yml +++ /dev/null @@ -1,20 +0,0 @@ -services: - batch_submitter: - depends_on: - - l1_chain - - deployer - - l2geth - build: - context: .. - dockerfile: ./ops/docker/Dockerfile.packages - target: batch-submitter - entrypoint: ./batches.sh - env_file: - - ./envs/batches.env - environment: - L1_NODE_WEB3_URL: http://l1_chain:8545 - L2_NODE_WEB3_URL: http://l2geth:8545 - URL: http://deployer:8081/addresses.json - SEQUENCER_PRIVATE_KEY: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d' - PROPOSER_PRIVATE_KEY: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a' - BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE: ${BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE:-zlib} diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 03469de8a2628..2e40b3bd8b04e 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -212,3 +212,22 @@ services: GAS_PRICE_ORACLE_ETHEREUM_HTTP_URL: http://l2geth:8545 # Default hardhat account 5 GAS_PRICE_ORACLE_PRIVATE_KEY: '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba' + + batch_submitter: + depends_on: + - l1_chain + - deployer + - l2geth + build: + context: .. + dockerfile: ./ops/docker/Dockerfile.batch-submitter-service + entrypoint: ./batch-submitter.sh + env_file: + - ./envs/batch-submitter.env + environment: + L1_ETH_RPC: http://l1_chain:8545 + L2_ETH_RPC: http://l2geth:8545 + URL: http://deployer:8081/addresses.json + BATCH_SUBMITTER_SEQUENCER_PRIVATE_KEY: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d' + BATCH_SUBMITTER_PROPOSER_PRIVATE_KEY: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a' + BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE: ${BATCH_SUBMITTER_SEQUENCER_BATCH_TYPE:-zlib} diff --git a/ops/docker/Dockerfile.batch-submitter b/ops/docker/Dockerfile.batch-submitter deleted file mode 100644 index a0b84461c5847..0000000000000 --- a/ops/docker/Dockerfile.batch-submitter +++ /dev/null @@ -1,35 +0,0 @@ -ARG LOCAL_REGISTRY=docker.io -ARG BUILDER_TAG=latest -FROM ${LOCAL_REGISTRY}/ethereumoptimism/builder:${BUILDER_TAG} AS builder - -FROM node:16-alpine - -RUN apk add --no-cache curl bash jq - -WORKDIR /opt/optimism - -# copy top level files -COPY --from=builder /optimism/*.json /optimism/yarn.lock ./ -COPY --from=builder /optimism/node_modules ./node_modules - -# copy deps (would have been nice if docker followed the symlinks required) -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/common-ts/package.json ./packages/common-ts/package.json -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/deployments ./packages/contracts/deployments -COPY --from=builder /optimism/packages/contracts/dist ./packages/contracts/dist -COPY --from=builder /optimism/packages/contracts/artifacts ./packages/contracts/artifacts - -# copy the service -WORKDIR /opt/optimism/packages/batch-submitter -COPY --from=builder /optimism/packages/batch-submitter/package.json ./ -COPY --from=builder /optimism/packages/batch-submitter/dist ./dist -COPY --from=builder /optimism/packages/batch-submitter/exec ./exec -COPY --from=builder /optimism/packages/batch-submitter/node_modules ./node_modules - -# copy this over in case you want to run alongside other services -COPY ./ops/scripts/batches.sh . -ENTRYPOINT ["npm", "run", "start"] diff --git a/ops/docker/Dockerfile.monorepo b/ops/docker/Dockerfile.monorepo index 63762076ada8a..e3b07a6a27df6 100644 --- a/ops/docker/Dockerfile.monorepo +++ b/ops/docker/Dockerfile.monorepo @@ -29,7 +29,6 @@ COPY packages/core-utils/package.json ./packages/core-utils/package.json COPY packages/common-ts/package.json ./packages/common-ts/package.json COPY packages/contracts/package.json ./packages/contracts/package.json COPY packages/data-transport-layer/package.json ./packages/data-transport-layer/package.json -COPY packages/batch-submitter/package.json ./packages/batch-submitter/package.json COPY packages/message-relayer/package.json ./packages/message-relayer/package.json COPY packages/replica-healthcheck/package.json ./packages/replica-healthcheck/package.json COPY integration-tests/package.json ./integration-tests/package.json diff --git a/ops/docker/Dockerfile.packages b/ops/docker/Dockerfile.packages index 119f94f046a09..e06cb37949b07 100644 --- a/ops/docker/Dockerfile.packages +++ b/ops/docker/Dockerfile.packages @@ -18,7 +18,6 @@ COPY packages/core-utils/package.json ./packages/core-utils/package.json COPY packages/common-ts/package.json ./packages/common-ts/package.json COPY packages/contracts/package.json ./packages/contracts/package.json COPY packages/data-transport-layer/package.json ./packages/data-transport-layer/package.json -COPY packages/batch-submitter/package.json ./packages/batch-submitter/package.json COPY packages/message-relayer/package.json ./packages/message-relayer/package.json COPY packages/replica-healthcheck/package.json ./packages/replica-healthcheck/package.json COPY integration-tests/package.json ./integration-tests/package.json @@ -38,12 +37,6 @@ COPY ./ops/scripts/deployer.sh . CMD ["yarn", "run", "deploy"] -FROM base as batch-submitter -WORKDIR /opt/optimism/packages/batch-submitter -COPY ./ops/scripts/batches.sh . -CMD ["npm", "run", "start"] - - FROM base as data-transport-layer WORKDIR /opt/optimism/packages/data-transport-layer COPY ./ops/scripts/dtl.sh . diff --git a/ops/envs/batches.env b/ops/envs/batches.env deleted file mode 100644 index 13017d3e6f7e7..0000000000000 --- a/ops/envs/batches.env +++ /dev/null @@ -1,19 +0,0 @@ -ADDRESS_MANAGER_ADDRESS= - -DEBUG=info*,error*,warn*,debug* - -MAX_L1_TX_SIZE=90000 -MIN_L1_TX_SIZE=32 -MAX_TX_BATCH_COUNT=50 -MAX_STATE_BATCH_COUNT=50 - -POLL_INTERVAL=500 -NUM_CONFIRMATIONS=0 -RESUBMISSION_TIMEOUT=1 -FINALITY_CONFIRMATIONS=0 -RUN_TX_BATCH_SUBMITTER=true -RUN_STATE_BATCH_SUBMITTER=true -MAX_BATCH_SUBMISSION_TIME=0 -SAFE_MINIMUM_ETHER_BALANCE=0 -CLEAR_PENDING_TXS=false -RETRIES=80 diff --git a/ops/scripts/batches.sh b/ops/scripts/batches.sh deleted file mode 100755 index 09c77db93c5c3..0000000000000 --- a/ops/scripts/batches.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e - -RETRIES=${RETRIES:-40} - -if [[ ! -z "$URL" ]]; then - # get the addrs from the URL provided - ADDRESSES=$(curl --fail --show-error --silent --retry-connrefused --retry $RETRIES --retry-delay 5 $URL) - # set the env - export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager') -fi - -# waits for l2geth to be up -curl --fail \ - --show-error \ - --silent \ - --retry-connrefused \ - --retry $RETRIES \ - --retry-delay 1 \ - --output /dev/null \ - $L2_NODE_WEB3_URL - -# go -exec node ./exec/run-batch-submitter.js diff --git a/ops/scripts/build-ci.sh b/ops/scripts/build-ci.sh index db85d1e80ec9e..682f29450730b 100755 --- a/ops/scripts/build-ci.sh +++ b/ops/scripts/build-ci.sh @@ -43,7 +43,6 @@ docker tag localhost:5000/ethereumoptimism/builder:latest ethereumoptimism/build build deployer "ethereumoptimism/deployer:latest" "./ops/docker/Dockerfile.deployer" . build dtl "ethereumoptimism/data-transport-layer:latest" "./ops/docker/Dockerfile.data-transport-layer" . -build batch_submitter "ethereumoptimism/batch-submitter:latest" "./ops/docker/Dockerfile.batch-submitter" . build relayer "ethereumoptimism/message-relayer:latest" "./ops/docker/Dockerfile.message-relayer" . build integration-tests "ethereumoptimism/integration-tests:latest" "./ops/docker/Dockerfile.integration-tests" . diff --git a/packages/batch-submitter/.env.example b/packages/batch-submitter/.env.example deleted file mode 100644 index 10789fa468153..0000000000000 --- a/packages/batch-submitter/.env.example +++ /dev/null @@ -1,43 +0,0 @@ -# Environment -NODE_ENV=development -# Leave blank during local development -ETH_NETWORK_NAME= -# Logging & monitoring -DEBUG=info*,error*,warn*,debug* -RUN_METRICS_SERVER= -METRICS_PORT= -METRICS_HOSTNAME= -# Leave the SENTRY_DSN variable unset during local development -SENTRY_DSN= -SENTRY_TRACE_RATE= -USE_SENTRY= - -L1_NODE_WEB3_URL=http://localhost:9545 -L2_NODE_WEB3_URL=http://localhost:8545 - -MAX_L1_TX_SIZE=90000 -MIN_L1_TX_SIZE=32 -MAX_TX_BATCH_SIZE=50 -MAX_STATE_BATCH_COUNT=2000 -MAX_TX_BATCH_COUNT=250 -MAX_BATCH_SUBMISSION_TIME=0 -POLL_INTERVAL=15000 -NUM_CONFIRMATIONS=0 -RESUBMISSION_TIMEOUT=300 # in seconds -FINALITY_CONFIRMATIONS=0 -RUN_TX_BATCH_SUBMITTER=true -RUN_STATE_BATCH_SUBMITTER=true -SAFE_MINIMUM_ETHER_BALANCE=0 -CLEAR_PENDING_TXS=false -ADDRESS_MANAGER_ADDRESS= - -USE_HARDHAT= -DEBUG_IMPERSONATE_SEQUENCER_ADDRESS= -DEBUG_IMPERSONATE_PROPOSER_ADDRESS= - -# Optional gas settings -MAX_GAS_PRICE_IN_GWEI=200 -GAS_RETRY_INCREMENT=5 -GAS_THRESHOLD_IN_GWEI=100 - -SEQUENCER_PRIVATE_KEY=0xd2ab07f7c10ac88d5f86f1b4c1035d5195e81f27dbe62ad65e59cbf88205629b diff --git a/packages/batch-submitter/.eslintrc.js b/packages/batch-submitter/.eslintrc.js deleted file mode 100644 index bfd2057be80bd..0000000000000 --- a/packages/batch-submitter/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: '../../.eslintrc.js', -} diff --git a/packages/batch-submitter/.lintstagedrc.yml b/packages/batch-submitter/.lintstagedrc.yml deleted file mode 100644 index a3035a2299b26..0000000000000 --- a/packages/batch-submitter/.lintstagedrc.yml +++ /dev/null @@ -1,2 +0,0 @@ -"*.{ts,js}": - - eslint diff --git a/packages/batch-submitter/.prettierrc.js b/packages/batch-submitter/.prettierrc.js deleted file mode 100644 index 6b3fa8e2ce237..0000000000000 --- a/packages/batch-submitter/.prettierrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - ...require('../../.prettierrc.js'), -}; \ No newline at end of file diff --git a/packages/batch-submitter/CHANGELOG.md b/packages/batch-submitter/CHANGELOG.md deleted file mode 100644 index 79dcba9af3aa2..0000000000000 --- a/packages/batch-submitter/CHANGELOG.md +++ /dev/null @@ -1,596 +0,0 @@ -# Changelog - -## 0.4.20 - -### Patch Changes - -- d3d70291: Use asL2Provider instead of injectL2Context in bss and healthcheck service. -- Updated dependencies [f37c283c] -- Updated dependencies [3f4d3c13] -- Updated dependencies [0b4453f7] -- Updated dependencies [78298782] -- Updated dependencies [0c54e60e] - - @eth-optimism/sdk@0.2.3 - - @eth-optimism/core-utils@0.8.0 - - @eth-optimism/contracts@0.5.15 - -## 0.4.19 - -### Patch Changes - -- Updated dependencies [b4165299] -- Updated dependencies [3c2acd91] - - @eth-optimism/core-utils@0.7.7 - - @eth-optimism/contracts@0.5.14 - -## 0.4.18 - -### Patch Changes - -- Updated dependencies [438bc78a] - - @eth-optimism/contracts@0.5.13 - -## 0.4.17 - -### Patch Changes - -- fcce5b67: Updates batch submitter to also include separate timestamps for deposit transactions" -- ba14c59d: Updates various ethers dependencies to their latest versions -- Updated dependencies [ba14c59d] - - @eth-optimism/contracts@0.5.12 - - @eth-optimism/core-utils@0.7.6 - -## 0.4.16 - -### Patch Changes - -- Updated dependencies [e631c39c] - - @eth-optimism/contracts@0.5.11 - -## 0.4.15 - -### Patch Changes - -- ae4a90d9: Adds a fix for the BSS to account for new timestamp logic in L2Geth -- ca547c4e: Import performance to not couple batch submitter to version of nodejs that has performance as a builtin -- Updated dependencies [ad94b9d1] - - @eth-optimism/core-utils@0.7.5 - - @eth-optimism/contracts@0.5.10 - -## 0.4.14 - -### Patch Changes - -- Updated dependencies [ba96a455] -- Updated dependencies [c3e85fef] - - @eth-optimism/core-utils@0.7.4 - - @eth-optimism/contracts@0.5.9 - -## 0.4.13 - -### Patch Changes - -- 9fe09f70: Properly clear state root batch txs on startup -- Updated dependencies [b3efb8b7] -- Updated dependencies [279603e5] -- Updated dependencies [b6040bb3] - - @eth-optimism/contracts@0.5.8 - -## 0.4.12 - -### Patch Changes - -- 07f1ad01: Fix the numTxPerBatch metric - -## 0.4.11 - -### Patch Changes - -- 3eb5590b: adds batchTxBuildTime gauge -- Updated dependencies [b6f89fad] - - @eth-optimism/contracts@0.5.7 - -## 0.4.10 - -### Patch Changes - -- Updated dependencies [bbd42e03] -- Updated dependencies [453f0774] - - @eth-optimism/contracts@0.5.6 - -## 0.4.9 - -### Patch Changes - -- 57d5b8f9: Build docker images with node.js version 16 - -## 0.4.8 - -### Patch Changes - -- 0ab37fc9: Update to node.js version 16 - -## 0.4.7 - -### Patch Changes - -- Updated dependencies [584cbc25] - - @eth-optimism/core-utils@0.7.3 - - @eth-optimism/contracts@0.5.5 - -## 0.4.6 - -### Patch Changes - -- 39607e7c: Trigger release of the batch submitter with yatm retry fix - -## 0.4.5 - -### Patch Changes - -- 85f68bd3: Immediately reject on nonce errors to stop falling behind - -## 0.4.4 - -### Patch Changes - -- 8e634b49: Fix package JSON issues -- Updated dependencies [8e634b49] - - @eth-optimism/core-utils@0.7.2 - - @eth-optimism/contracts@0.5.4 - -## 0.4.3 - -### Patch Changes - -- Updated dependencies [b9049406] -- Updated dependencies [a8b14a7d] - - @eth-optimism/contracts@0.5.3 - -## 0.4.2 - -### Patch Changes - -- 526d7e51: Throw an error when sequencer and proposer have the same address. -- 243f33e5: Standardize package json file format -- Updated dependencies [243f33e5] - - @eth-optimism/common-ts@0.2.1 - - @eth-optimism/contracts@0.5.2 - - @eth-optimism/core-utils@0.7.1 - -## 0.4.1 - -### Patch Changes - -- Updated dependencies [c0fc7fee] - - @eth-optimism/contracts@0.5.1 - -## 0.4.0 - -### Minor Changes - -- 3f590e33: Remove the "OVM" Prefix from contract names -- 81ccd6e4: `regenesis/0.5.0` release - -### Patch Changes - -- ac63235a: Default tx batch validation to false -- bfeb7fba: Add `VALIDATE_TX_BATCH` config option that can disable batch validation -- 222a3eef: Add 'User-Agent' to the http headers for ethers providers -- 71f8de9c: Handle error case more explicity when creating invalid batch -- 970f421e: Ensure empty batches are not submitted -- b70ee70c: upgraded to solidity 0.8.9 -- a98a1884: Fixes dependencies instead of using caret constraints -- Updated dependencies [e4a1129c] -- Updated dependencies [64ea3ac9] -- Updated dependencies [3ce62c81] -- Updated dependencies [299a459e] -- Updated dependencies [8c8807c0] -- Updated dependencies [d7978cfc] -- Updated dependencies [e16d41c0] -- Updated dependencies [5db50b3d] -- Updated dependencies [cee2a464] -- Updated dependencies [66bf56a6] -- Updated dependencies [2c91ca00] -- Updated dependencies [d5036826] -- Updated dependencies [222a3eef] -- Updated dependencies [dfc784e8] -- Updated dependencies [896168e2] -- Updated dependencies [436c48fd] -- Updated dependencies [7c352b1e] -- Updated dependencies [2ade9a79] -- Updated dependencies [0272a536] -- Updated dependencies [6ee7423f] -- Updated dependencies [3f590e33] -- Updated dependencies [e20deca0] -- Updated dependencies [2a731e0d] -- Updated dependencies [199e895e] -- Updated dependencies [872f5976] -- Updated dependencies [9c1443a4] -- Updated dependencies [26906518] -- Updated dependencies [c53b3587] -- Updated dependencies [1b917041] -- Updated dependencies [483f561b] -- Updated dependencies [b70ee70c] -- Updated dependencies [c38e4b57] -- Updated dependencies [a98a1884] -- Updated dependencies [b744b6ea] -- Updated dependencies [20c8969b] -- Updated dependencies [d2eb8ae0] -- Updated dependencies [1e63ffa0] -- Updated dependencies [ff266e9c] -- Updated dependencies [b56dd079] -- Updated dependencies [56fe3793] -- Updated dependencies [3e2aa16a] -- Updated dependencies [d3cb1b86] -- Updated dependencies [3e41df63] -- Updated dependencies [973589da] -- Updated dependencies [83a449c4] -- Updated dependencies [9c63e9bd] -- Updated dependencies [81ccd6e4] -- Updated dependencies [f38b8000] -- Updated dependencies [d5f012ab] -- Updated dependencies [76c84f21] -- Updated dependencies [6d32d701] -- Updated dependencies [3605b963] -- Updated dependencies [3f28385a] -- Updated dependencies [280f348c] -- Updated dependencies [a0947c3f] -- Updated dependencies [51821d8f] -- Updated dependencies [29f1c228] -- Updated dependencies [8f4cb337] -- Updated dependencies [beb6c977] -- Updated dependencies [33abe73d] -- Updated dependencies [71de86d6] - - @eth-optimism/contracts@0.5.0 - - @eth-optimism/core-utils@0.7.0 - - @eth-optimism/common-ts@0.2.0 - -## 0.3.15 - -### Patch Changes - -- 6d3e1d7f: Update dependencies -- Updated dependencies [6d3e1d7f] -- Updated dependencies [2e929aa9] - - @eth-optimism/common-ts@0.1.6 - - @eth-optimism/contracts@0.4.14 - - @eth-optimism/core-utils@0.6.1 - -## 0.3.14 - -### Patch Changes - -- 39cea8fd: Removes the call to `appendQueueBatch` from the batch submitter -- Updated dependencies [e0be02e1] -- Updated dependencies [7f7f35c3] -- Updated dependencies [8da04505] - - @eth-optimism/core-utils@0.6.0 - - @eth-optimism/contracts@0.4.13 - -## 0.3.13 - -### Patch Changes - -- 7482d09c: Fixes a bug in the batch submitted that would cause it to submit transactions with increasing nonces - -## 0.3.12 - -### Patch Changes - -- 21b17edd: Added coverage for packages -- 78ca518b: Add loglines for eip1559 related fields before sending a transaction -- Updated dependencies [888dafca] -- Updated dependencies [eb0854e7] -- Updated dependencies [21b17edd] -- Updated dependencies [dfe3598f] - - @eth-optimism/contracts@0.4.11 - - @eth-optimism/core-utils@0.5.5 - -## 0.3.11 - -### Patch Changes - -- 918c08ca: Bump ethers dependency to 5.4.x to support eip1559 -- Updated dependencies [918c08ca] - - @eth-optimism/contracts@0.4.10 - - @eth-optimism/core-utils@0.5.2 - -## 0.3.10 - -### Patch Changes - -- b5b9fd89: Migrate to using `ethers.StaticJsonRpcProvider` -- Updated dependencies [ecc2f8c1] - - @eth-optimism/contracts@0.4.9 - -## 0.3.9 - -### Patch Changes - -- 3b132974: Fix tx resubmission estimateGas bug in batch submitter -- Updated dependencies [7f26667d] -- Updated dependencies [77511b68] - - @eth-optimism/contracts@0.4.7 - -## 0.3.8 - -### Patch Changes - -- c73c3939: Update the typescript version to `4.3.5` -- Updated dependencies [c73c3939] - - @eth-optimism/common-ts@0.1.5 - - @eth-optimism/contracts@0.4.5 - - @eth-optimism/core-utils@0.5.1 - -## 0.3.7 - -### Patch Changes - -- 8a1e63dd: Prevent batch submitter from submitting batches if low on ETH -- Updated dependencies [0313794b] -- Updated dependencies [049200f4] -- Updated dependencies [21e47e1f] - - @eth-optimism/contracts@0.4.2 - - @eth-optimism/core-utils@0.5.0 - -## 0.3.6 - -### Patch Changes - -- f87a2d00: Use dashes instead of colons in contract names -- 52d02b14: Add failure metrics to batch submitter -- 31f517a2: Improved logging of batch submission timeout logs -- 5c89c45f: Move the metric prefix string to a label #1047 -- Updated dependencies [25f09abd] -- Updated dependencies [dd8edc7b] -- Updated dependencies [c87e4c74] -- Updated dependencies [db0dbfb2] -- Updated dependencies [7f5936a8] -- Updated dependencies [f87a2d00] -- Updated dependencies [85da4979] -- Updated dependencies [57ca21a2] -- Updated dependencies [5fc728da] -- Updated dependencies [2e72fd90] -- Updated dependencies [c43b33ec] -- Updated dependencies [26bc63ad] -- Updated dependencies [a0d9e565] -- Updated dependencies [2bd49730] -- Updated dependencies [38355a3b] -- Updated dependencies [3c2c32e1] -- Updated dependencies [d9644c34] -- Updated dependencies [48ece14c] -- Updated dependencies [e04de624] -- Updated dependencies [014dea71] -- Updated dependencies [fa29b03e] -- Updated dependencies [6b46c8ba] -- Updated dependencies [e045f582] -- Updated dependencies [5c89c45f] -- Updated dependencies [df5ff890] -- Updated dependencies [e29fab10] -- Updated dependencies [c2a04893] -- Updated dependencies [baacda34] - - @eth-optimism/contracts@0.4.0 - - @eth-optimism/core-utils@0.4.6 - - @eth-optimism/common-ts@0.1.4 - -## 0.3.5 - -### Patch Changes - -- 7cce55a9: Add status to generic error log to disambiguate errors - -## 0.3.4 - -### Patch Changes - -- baa3b761: Improve Sentry support, initializing as needed and ensuring ERROR logs route to Sentry -- cc742715: Fix typo in USE_HARDHAT config -- 98b7839f: Change monotonicity band-aid code to log warnings not errors -- c520100d: Fix a bug in fixMonotonicity auto healer -- 85362d44: Log additional data in monotonicity violation -- Updated dependencies [baa3b761] - - @eth-optimism/common-ts@0.1.3 - -## 0.3.3 - -### Patch Changes - -- 750a5021: Remove dead imports from core-utils -- Updated dependencies [a64f8161] -- Updated dependencies [4e03f8a9] -- Updated dependencies [8e2bfd07] -- Updated dependencies [750a5021] -- Updated dependencies [c2b6e14b] -- Updated dependencies [245136f1] - - @eth-optimism/core-utils@0.4.5 - - @eth-optimism/contracts@0.3.5 - -## 0.3.2 - -### Patch Changes - -- 4340bb1: Fix: correctly read Batch Submitter env var defaults - -## 0.3.1 - -### Patch Changes - -- c79dc8b: Add impersonate account debug config. -- 0c16805: add metrics server to common-ts and batch submitter -- fa4898a: Explicitly log error messages so that they do not show as empty objects -- 96a586e: Updates the configuration to use bcfg in a backwards compatible way -- c79dc8b: Make BLOCK_OFFSET configurable. -- Updated dependencies [96a586e] -- Updated dependencies [0c16805] -- Updated dependencies [775118a] - - @eth-optimism/core-utils@0.4.3 - - @eth-optimism/common-ts@0.1.2 - - @eth-optimism/contracts@0.3.1 - -## 0.3.0 - -### Minor Changes - -- b799caa: Updates to use RLP encoded transactions in batches for the `v0.3.0` release - -### Patch Changes - -- 751e2be: Add the support for different sequencer & proposer keys in the batch submitter. -- Updated dependencies [b799caa] -- Updated dependencies [6132e7a] -- Updated dependencies [b799caa] -- Updated dependencies [b799caa] -- Updated dependencies [b799caa] -- Updated dependencies [20747fd] -- Updated dependencies [b799caa] -- Updated dependencies [b799caa] - - @eth-optimism/contracts@0.3.0 - - @eth-optimism/core-utils@0.4.2 - -## 0.2.5 - -### Patch Changes - -- 1d40586: Removed various unused dependencies -- Updated dependencies [1d40586] -- Updated dependencies [ce7fa52] -- Updated dependencies [575bcf6] -- Updated dependencies [6dc1877] - - @eth-optimism/common-ts@0.1.1 - - @eth-optimism/contracts@0.2.10 - - @eth-optimism/core-utils@0.4.1 - -## 0.2.4 - -### Patch Changes - -- 12dbd81: add key metrics to batch submitter -- 28dc442: move metrics, logger, and base-service to new common-ts package -- 79df44e: Add skipped deposit auto heal -- Updated dependencies [28dc442] -- Updated dependencies [d2091d4] -- Updated dependencies [a0a0052] -- Updated dependencies [0ef3069] - - @eth-optimism/common-ts@0.1.0 - - @eth-optimism/core-utils@0.4.0 - - @eth-optimism/contracts@0.2.9 - -## 0.2.3 - -### Patch Changes - -- 6daa408: update hardhat versions so that solc is resolved correctly -- dee74ef: migrate batch submitter types to core-utils -- d64b66d: reformat error context for Sentry -- Updated dependencies [6daa408] -- Updated dependencies [ea4041b] -- Updated dependencies [f1f5bf2] -- Updated dependencies [dee74ef] -- Updated dependencies [9ec3ec0] -- Updated dependencies [d64b66d] -- Updated dependencies [5f376ee] -- Updated dependencies [eef1df4] -- Updated dependencies [a76cde5] -- Updated dependencies [e713cd0] -- Updated dependencies [572dcbc] -- Updated dependencies [6014ec0] - - @eth-optimism/contracts@0.2.8 - - @eth-optimism/core-utils@0.3.2 - -## 0.2.2 - -### Patch Changes - -- 6d31324: Update release tag for Sentry compatability -- a2f6e83: add default metrics to all batch submitters - -## 0.2.1 - -### Patch Changes - -- ab285e4: properly start the batch submitter instead of instantly exiting - -## 0.2.0 - -### Minor Changes - -- 5077441: - Use raw transaction in batch submitter -- incompatible with L2Geth v0.1.2.1 - - Pass through raw transaction in l2context - -### Patch Changes - -- a3dc553: Adds a release version to batch-submitter and data-transport-layer usage of Sentry -- b95dc22: log errors for monotonicity violations -- c7bc0ce: Correctly formatted error object to log exceptions -- Updated dependencies [ce5d596] -- Updated dependencies [1a55f64] -- Updated dependencies [6e8fe1b] -- Updated dependencies [8d4aae4] -- Updated dependencies [c75a0fc] -- Updated dependencies [d4ee2d7] -- Updated dependencies [edb4346] -- Updated dependencies [5077441] - - @eth-optimism/contracts@0.2.6 - - @eth-optimism/core-utils@0.3.1 - -## 0.1.12 - -### Patch Changes - -- a0a7956: initialize Sentry and streams in Logger, remove Sentry from Batch Submitter -- Updated dependencies [91460d9] -- Updated dependencies [a0a7956] -- Updated dependencies [0497d7d] - - @eth-optimism/core-utils@0.3.0 - - @eth-optimism/contracts@0.2.5 - -## 0.1.11 - -### Patch Changes - -- 35b99b0: add Sentry to TypeScript services for error tracking -- Updated dependencies [35b99b0] - - @eth-optimism/core-utils@0.2.3 - -## 0.1.10 - -### Patch Changes - -- 962e31b: removed unused l1 block number logic, added debug logging to batch submitter - -## 0.1.9 - -### Patch Changes - -- 3b00b7c: bump private package versions to try triggering a tag - -## 0.1.8 - -### Patch Changes - -- 6cbc54d: allow injecting L2 transaction and block context via core-utils (this removes the need to import the now deprecated @eth-optimism/provider package) -- Updated dependencies [6cbc54d] - - @eth-optimism/core-utils@0.2.0 - - @eth-optimism/contracts@0.2.2 - -## v0.1.3 - -- Add tx resubmission logic -- Log when the batch submitter runs low on ETH - -## v0.1.2 - -Adds mnemonic config parsing - -## v0.1.1 - -Final fixes before minnet release. - -- Add batch submission timeout -- Log sequencer address -- remove ssh - -## v0.1.0 - -The inital release diff --git a/packages/batch-submitter/LICENSE b/packages/batch-submitter/LICENSE deleted file mode 100644 index 6a7da5218bb25..0000000000000 --- a/packages/batch-submitter/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -(The MIT License) - -Copyright 2020-2021 Optimism - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/batch-submitter/README.md b/packages/batch-submitter/README.md deleted file mode 100644 index 1a8f5ad3e241b..0000000000000 --- a/packages/batch-submitter/README.md +++ /dev/null @@ -1,45 +0,0 @@ -[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/master/graph/badge.svg?token=0VTG7PG7YR&flag=batch-submitter)](https://codecov.io/gh/ethereum-optimism/optimism) -# Batch Submitter - -Contains an executable batch submitter service which watches L1 and a local L2 node and submits batches to the -`CanonicalTransactionChain` & `StateCommitmentChain` based on its local information. - -## Configuration -All configuration is done via environment variables. See all variables at [.env.example](.env.example); copy into a `.env` file before running. - -## Building & Running -1. Make sure dependencies are installed just run `yarn` in the base directory -2. Build `yarn build` -3. Run `yarn start` - -## Controlling log output verbosity -Before running, set the `DEBUG` environment variable to specify the verbosity level. It must be made up of comma-separated values of patterns to match in debug logs. Here's a few common options: -* `debug*` - Will match all debug statements -- very verbose -* `info*` - Will match all info statements -- less verbose, useful in most cases -* `warn*` - Will match all warnings -- recommended at a minimum -* `error*` - Will match all errors -- would not omit this - -Examples: -* Everything but debug: `export DEBUG=info*,error*,warn*` -* Most verbose: `export DEBUG=info*,error*,warn*,debug*` - -## Testing & linting - -### Local - -- Run unit tests with `yarn test` -- See lint errors with `yarn lint`; auto-fix with `yarn lint --fix` - -### Submission - -You may test a submission locally against a local Hardhat fork. - -1. Follow the instructions [here](https://github.com/ethereum-optimism/hardhat) to run a Hardhat node. -2. Change the Batch Submitter `.env` field `L1_NODE_WEB3_URL` to the local Hardhat url. Depending on which network you are using, update `ADDRESS_MANAGER_ADDRESS` according to the [Regenesis repo](https://github.com/ethereum-optimism/regenesis). -3. Also check `L2_NODE_WEB3_URL` is correctly set and has transactions to submit. -3. Run `yarn build` to build your changes. -4. Start Batch Submitter with `yarn start`. It will automatically start submitting pending transactions from L2. - -## Observability in production - -When deploying Batch Submitter to production / a live ETH network, populate the environment variables `NODE_ENV` (`development`, `production`, or `test`) and `ETH_NETWORK_NAME` (`mainnet`, `kovan`, `goerli`). This enables Batch Submitter to capture more context in logs and metrics, and initializes [Sentry](https://docs.sentry.io/platforms/node/) to track errors. diff --git a/packages/batch-submitter/exec/run-batch-submitter.js b/packages/batch-submitter/exec/run-batch-submitter.js deleted file mode 100755 index 4241cf3e5aee1..0000000000000 --- a/packages/batch-submitter/exec/run-batch-submitter.js +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env node - -const batchSubmitter = require('../dist/src/exec/run-batch-submitter') - -batchSubmitter.run() diff --git a/packages/batch-submitter/hardhat.config.ts b/packages/batch-submitter/hardhat.config.ts deleted file mode 100644 index b49f641649589..0000000000000 --- a/packages/batch-submitter/hardhat.config.ts +++ /dev/null @@ -1,40 +0,0 @@ -import '@nomiclabs/hardhat-waffle' -import { HardhatUserConfig } from 'hardhat/config' - -import { - DEFAULT_ACCOUNTS_HARDHAT, - RUN_OVM_TEST_GAS, -} from './test/helpers/constants' - -import '@nomiclabs/hardhat-ethers' - -const config: HardhatUserConfig = { - networks: { - hardhat: { - accounts: DEFAULT_ACCOUNTS_HARDHAT, - blockGasLimit: RUN_OVM_TEST_GAS * 2, - }, - }, - mocha: { - timeout: 50000, - }, - solidity: { - version: '0.7.0', - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - metadata: { - bytecodeHash: 'none', - }, - outputSelection: { - '*': { - '*': ['metadata', 'storageLayout'], - }, - }, - }, - }, -} - -export default config diff --git a/packages/batch-submitter/index.ts b/packages/batch-submitter/index.ts deleted file mode 100644 index 4627ee1cefffb..0000000000000 --- a/packages/batch-submitter/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -const rootPath = __dirname - -export { rootPath } diff --git a/packages/batch-submitter/package.json b/packages/batch-submitter/package.json deleted file mode 100644 index 17abede61036e..0000000000000 --- a/packages/batch-submitter/package.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "private": true, - "name": "@eth-optimism/batch-submitter", - "version": "0.4.20", - "description": "[Optimism] Service for submitting transactions and transaction results", - "main": "dist/index", - "types": "dist/index", - "files": [ - "dist/*" - ], - "scripts": { - "start": "node ./exec/run-batch-submitter.js", - "build": "tsc -p ./tsconfig.build.json", - "clean": "rimraf cache/ dist/ ./tsconfig.build.tsbuildinfo", - "lint": "yarn lint:fix && yarn lint:check", - "pre-commit": "lint-staged", - "lint:fix": "yarn lint:check --fix", - "lint:check": "eslint . --max-warnings=0", - "test": "hardhat test --show-stack-traces", - "test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json" - }, - "keywords": [ - "optimism", - "ethereum", - "sequencer", - "aggregator" - ], - "homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/packages/batch-submitter#readme", - "license": "MIT", - "author": "Optimism PBC", - "repository": { - "type": "git", - "url": "https://github.com/ethereum-optimism/optimism.git" - }, - "dependencies": { - "@eth-optimism/common-ts": "0.2.1", - "@eth-optimism/contracts": "0.5.15", - "@eth-optimism/core-utils": "0.8.0", - "@eth-optimism/sdk": "^0.2.3", - "@eth-optimism/ynatm": "^0.2.2", - "@ethersproject/abstract-provider": "^5.5.1", - "@ethersproject/providers": "^5.5.3", - "@sentry/node": "^6.3.1", - "bcfg": "^0.1.6", - "bluebird": "^3.7.2", - "dotenv": "^10.0.0", - "ethers": "^5.5.4", - "old-contracts": "npm:@eth-optimism/contracts@^0.0.2-alpha.7", - "prom-client": "^13.1.0" - }, - "devDependencies": { - "@eth-optimism/smock": "1.1.10", - "@nomiclabs/hardhat-ethers": "^2.0.2", - "@nomiclabs/hardhat-waffle": "^2.0.1", - "@types/bluebird": "^3.5.34", - "@types/chai": "^4.2.18", - "@types/mocha": "^8.2.2", - "@types/node": "^15.12.2", - "@types/sinon": "^9.0.10", - "@types/sinon-chai": "^3.2.5", - "@typescript-eslint/eslint-plugin": "^4.26.0", - "@typescript-eslint/parser": "^4.26.0", - "babel-eslint": "^10.1.0", - "chai": "^4.3.4", - "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", - "hardhat": "^2.3.0", - "lint-staged": "11.0.0", - "mocha": "^8.4.0", - "prettier": "^2.3.1", - "rimraf": "^3.0.2", - "sinon": "^9.2.4", - "sinon-chai": "^3.5.0", - "typescript": "^4.3.5" - }, - "resolutions": { - "ganache-core": "^2.13.2", - "**/@sentry/node": "^6.2.5" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/batch-submitter/src/batch-submitter/batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/batch-submitter.ts deleted file mode 100644 index 40418adcd0f76..0000000000000 --- a/packages/batch-submitter/src/batch-submitter/batch-submitter.ts +++ /dev/null @@ -1,305 +0,0 @@ -/* External Imports */ -import { - Contract, - Signer, - utils, - providers, - PopulatedTransaction, -} from 'ethers' -import { - TransactionReceipt, - TransactionResponse, -} from '@ethersproject/abstract-provider' -import { Gauge, Histogram, Counter } from 'prom-client' -import { RollupInfo, sleep } from '@eth-optimism/core-utils' -import { Logger, Metrics } from '@eth-optimism/common-ts' -import { getContractFactory } from 'old-contracts' - -/* Internal Imports */ -import { TxSubmissionHooks } from '..' - -export interface BlockRange { - start: number - end: number -} - -interface BatchSubmitterMetrics { - batchSubmitterETHBalance: Gauge - batchSizeInBytes: Histogram - numTxPerBatch: Histogram - submissionTimestamp: Histogram - submissionGasUsed: Histogram - batchesSubmitted: Counter - failedSubmissions: Counter - malformedBatches: Counter - batchTxBuildTime: Gauge -} - -export abstract class BatchSubmitter { - protected rollupInfo: RollupInfo - protected chainContract: Contract - protected l2ChainId: number - protected syncing: boolean - protected lastBatchSubmissionTimestamp: number = 0 - protected metrics: BatchSubmitterMetrics - - constructor( - readonly signer: Signer, - readonly l2Provider: providers.StaticJsonRpcProvider, - readonly minTxSize: number, - readonly maxTxSize: number, - readonly maxBatchSize: number, - readonly maxBatchSubmissionTime: number, - readonly numConfirmations: number, - readonly resubmissionTimeout: number, - readonly finalityConfirmations: number, - readonly addressManagerAddress: string, - readonly minBalanceEther: number, - readonly blockOffset: number, - readonly logger: Logger, - readonly defaultMetrics: Metrics - ) { - this.metrics = this._registerMetrics(defaultMetrics) - } - - public abstract _submitBatch( - startBlock: number, - endBlock: number - ): Promise - public abstract _onSync(): Promise - public abstract _getBatchStartAndEnd(): Promise - public abstract _updateChainInfo(): Promise - - public async submitNextBatch(): Promise { - if (typeof this.l2ChainId === 'undefined') { - this.l2ChainId = await this._getL2ChainId() - } - await this._updateChainInfo() - - if (!(await this._hasEnoughETHToCoverGasCosts())) { - await sleep(this.resubmissionTimeout) - return - } - - this.logger.info('Readying to submit next batch...', { - l2ChainId: this.l2ChainId, - batchSubmitterAddress: await this.signer.getAddress(), - }) - - if (this.syncing === true) { - this.logger.info( - 'Syncing mode enabled! Skipping batch submission and clearing queue...' - ) - return this._onSync() - } - const range = await this._getBatchStartAndEnd() - if (!range) { - return - } - - return this._submitBatch(range.start, range.end) - } - - protected async _hasEnoughETHToCoverGasCosts(): Promise { - const address = await this.signer.getAddress() - const balance = await this.signer.getBalance() - const ether = utils.formatEther(balance) - const num = parseFloat(ether) - - this.logger.info('Checked balance', { - address, - ether, - }) - - this.metrics.batchSubmitterETHBalance.set(num) - - if (num < this.minBalanceEther) { - this.logger.fatal('Current balance lower than min safe balance', { - current: num, - safeBalance: this.minBalanceEther, - }) - return false - } - - return true - } - - protected async _getRollupInfo(): Promise { - return this.l2Provider.send('rollup_getInfo', []) - } - - protected async _getL2ChainId(): Promise { - return this.l2Provider.send('eth_chainId', []) - } - - protected async _getChainAddresses(): Promise<{ - ctcAddress: string - sccAddress: string - }> { - const addressManager = ( - await getContractFactory('Lib_AddressManager', this.signer) - ).attach(this.addressManagerAddress) - const sccAddress = await addressManager.getAddress('StateCommitmentChain') - const ctcAddress = await addressManager.getAddress( - 'CanonicalTransactionChain' - ) - return { - ctcAddress, - sccAddress, - } - } - - protected _shouldSubmitBatch(batchSizeInBytes: number): boolean { - const currentTimestamp = Date.now() - if (batchSizeInBytes < this.minTxSize) { - const timeSinceLastSubmission = - currentTimestamp - this.lastBatchSubmissionTimestamp - if (timeSinceLastSubmission < this.maxBatchSubmissionTime) { - this.logger.info( - 'Skipping batch submission. Batch too small & max submission timeout not reached.', - { - batchSizeInBytes, - timeSinceLastSubmission, - maxBatchSubmissionTime: this.maxBatchSubmissionTime, - minTxSize: this.minTxSize, - lastBatchSubmissionTimestamp: this.lastBatchSubmissionTimestamp, - currentTimestamp, - } - ) - return false - } - this.logger.info('Timeout reached, proceeding with batch submission.', { - batchSizeInBytes, - timeSinceLastSubmission, - maxBatchSubmissionTime: this.maxBatchSubmissionTime, - lastBatchSubmissionTimestamp: this.lastBatchSubmissionTimestamp, - currentTimestamp, - }) - this.metrics.batchSizeInBytes.observe(batchSizeInBytes) - return true - } - this.logger.info( - 'Sufficient batch size, proceeding with batch submission.', - { - batchSizeInBytes, - lastBatchSubmissionTimestamp: this.lastBatchSubmissionTimestamp, - currentTimestamp, - } - ) - this.metrics.batchSizeInBytes.observe(batchSizeInBytes) - return true - } - - protected _makeHooks(txName: string): TxSubmissionHooks { - return { - beforeSendTransaction: (tx: PopulatedTransaction) => { - this.logger.info(`Submitting ${txName} transaction`, { - gasPrice: tx.gasPrice, - maxFeePerGas: tx.maxFeePerGas, - maxPriorityFeePerGas: tx.maxPriorityFeePerGas, - gasLimit: tx.gasLimit, - nonce: tx.nonce, - contractAddr: this.chainContract.address, - }) - }, - onTransactionResponse: (txResponse: TransactionResponse) => { - this.logger.info(`Submitted ${txName} transaction`, { - txHash: txResponse.hash, - from: txResponse.from, - }) - this.logger.debug(`${txName} transaction data`, { - data: txResponse.data, - }) - }, - } - } - - protected async _submitAndLogTx( - submitTransaction: () => Promise, - successMessage: string - ): Promise { - this.lastBatchSubmissionTimestamp = Date.now() - this.logger.debug('Submitting transaction & waiting for receipt...') - - let receipt: TransactionReceipt - try { - receipt = await submitTransaction() - } catch (err) { - this.metrics.failedSubmissions.inc() - if (err.reason) { - this.logger.error(`Transaction invalid: ${err.reason}, aborting`, { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - return - } - - this.logger.error('Encountered error at submission, aborting', { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - return - } - - this.logger.info('Received transaction receipt', { receipt }) - this.logger.info(successMessage) - this.metrics.batchesSubmitted.inc() - this.metrics.submissionGasUsed.observe(receipt.gasUsed.toNumber()) - this.metrics.submissionTimestamp.observe(Date.now()) - return receipt - } - - private _registerMetrics(metrics: Metrics): BatchSubmitterMetrics { - metrics.registry.clear() - - return { - batchSubmitterETHBalance: new metrics.client.Gauge({ - name: 'batch_submitter_eth_balance', - help: 'ETH balance of the batch submitter', - registers: [metrics.registry], - }), - batchSizeInBytes: new metrics.client.Histogram({ - name: 'batch_size_in_bytes', - help: 'Size of batches in bytes', - registers: [metrics.registry], - }), - numTxPerBatch: new metrics.client.Histogram({ - name: 'num_txs_per_batch', - help: 'Number of transactions in each batch', - registers: [metrics.registry], - }), - submissionTimestamp: new metrics.client.Histogram({ - name: 'submission_timestamp', - help: 'Timestamp of each batch submitter submission', - registers: [metrics.registry], - }), - submissionGasUsed: new metrics.client.Histogram({ - name: 'submission_gash_used', - help: 'Gas used to submit each batch', - registers: [metrics.registry], - }), - batchesSubmitted: new metrics.client.Counter({ - name: 'batches_submitted', - help: 'Count of batches submitted', - registers: [metrics.registry], - }), - failedSubmissions: new metrics.client.Counter({ - name: 'failed_submissions', - help: 'Count of failed batch submissions', - registers: [metrics.registry], - }), - malformedBatches: new metrics.client.Counter({ - name: 'malformed_batches', - help: 'Count of malformed batches', - registers: [metrics.registry], - }), - batchTxBuildTime: new metrics.client.Gauge({ - name: 'batch_tx_build_time', - help: 'Time to construct batch transaction', - registers: [metrics.registry], - }), - } - } -} diff --git a/packages/batch-submitter/src/batch-submitter/index.ts b/packages/batch-submitter/src/batch-submitter/index.ts deleted file mode 100644 index 0b96dc9a09d38..0000000000000 --- a/packages/batch-submitter/src/batch-submitter/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './batch-submitter' -export * from './tx-batch-submitter' -export * from './state-batch-submitter' - -export const TX_BATCH_SUBMITTER_LOG_TAG = 'oe:batch_submitter:tx_chain' -export const STATE_BATCH_SUBMITTER_LOG_TAG = 'oe:batch_submitter:state_chain' diff --git a/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts deleted file mode 100644 index 15c452c52dbb4..0000000000000 --- a/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts +++ /dev/null @@ -1,253 +0,0 @@ -/* External Imports */ -import { performance } from 'perf_hooks' - -import { Promise as bPromise } from 'bluebird' -import { Contract, Signer, providers } from 'ethers' -import { TransactionReceipt } from '@ethersproject/abstract-provider' -import { getContractFactory } from 'old-contracts' -import { - L2Block, - RollupInfo, - Bytes32, - remove0x, -} from '@eth-optimism/core-utils' -import { Logger, Metrics } from '@eth-optimism/common-ts' - -/* Internal Imports */ -import { TransactionSubmitter } from '../utils' -import { BlockRange, BatchSubmitter } from '.' - -export class StateBatchSubmitter extends BatchSubmitter { - // TODO: Change this so that we calculate start = scc.totalElements() and end = ctc.totalElements()! - // Not based on the length of the L2 chain -- that is only used in the batch submitter - // Note this means we've got to change the state / end calc logic - - protected l2ChainId: number - protected syncing: boolean - protected ctcContract: Contract - private fraudSubmissionAddress: string - private transactionSubmitter: TransactionSubmitter - - constructor( - signer: Signer, - l2Provider: providers.StaticJsonRpcProvider, - minTxSize: number, - maxTxSize: number, - maxBatchSize: number, - maxBatchSubmissionTime: number, - numConfirmations: number, - resubmissionTimeout: number, - finalityConfirmations: number, - addressManagerAddress: string, - minBalanceEther: number, - transactionSubmitter: TransactionSubmitter, - blockOffset: number, - logger: Logger, - metrics: Metrics, - fraudSubmissionAddress: string - ) { - super( - signer, - l2Provider, - minTxSize, - maxTxSize, - maxBatchSize, - maxBatchSubmissionTime, - numConfirmations, - resubmissionTimeout, - finalityConfirmations, - addressManagerAddress, - minBalanceEther, - blockOffset, - logger, - metrics - ) - this.fraudSubmissionAddress = fraudSubmissionAddress - this.transactionSubmitter = transactionSubmitter - } - - /***************************** - * Batch Submitter Overrides * - ****************************/ - - public async _updateChainInfo(): Promise { - const info: RollupInfo = await this._getRollupInfo() - if (info.mode === 'verifier') { - this.logger.error( - 'Verifier mode enabled! Batch submitter only compatible with sequencer mode' - ) - process.exit(1) - } - this.syncing = info.syncing - const addrs = await this._getChainAddresses() - const sccAddress = addrs.sccAddress - const ctcAddress = addrs.ctcAddress - - if ( - typeof this.chainContract !== 'undefined' && - sccAddress === this.chainContract.address && - ctcAddress === this.ctcContract.address - ) { - this.logger.debug('Chain contract already initialized', { - sccAddress, - ctcAddress, - }) - return - } - - this.chainContract = ( - await getContractFactory('OVM_StateCommitmentChain', this.signer) - ).attach(sccAddress) - this.ctcContract = ( - await getContractFactory('OVM_CanonicalTransactionChain', this.signer) - ).attach(ctcAddress) - - this.logger.info('Connected Optimism contracts', { - stateCommitmentChain: this.chainContract.address, - canonicalTransactionChain: this.ctcContract.address, - }) - return - } - - public async _onSync(): Promise { - this.logger.info('Syncing mode enabled! Skipping state batch submission...') - return - } - - public async _getBatchStartAndEnd(): Promise { - this.logger.info('Getting batch start and end for state batch submitter...') - const startBlock: number = - (await this.chainContract.getTotalElements()).toNumber() + - this.blockOffset - this.logger.info('Retrieved start block number from SCC', { - startBlock, - }) - - // We will submit state roots for txs which have been in the tx chain for a while. - const totalElements: number = - (await this.ctcContract.getTotalElements()).toNumber() + this.blockOffset - this.logger.info('Retrieved total elements from CTC', { - totalElements, - }) - - const endBlock: number = Math.min( - startBlock + this.maxBatchSize, - totalElements - ) - - if (startBlock >= endBlock) { - if (startBlock > endBlock) { - this.logger.error( - 'State commitment chain is larger than transaction chain. This should never happen!' - ) - } - this.logger.info( - 'No state commitments to submit. Skipping batch submission...' - ) - return - } - return { - start: startBlock, - end: endBlock, - } - } - - public async _submitBatch( - startBlock: number, - endBlock: number - ): Promise { - const batchTxBuildStart = performance.now() - - const batch = await this._generateStateCommitmentBatch(startBlock, endBlock) - const calldata = this.chainContract.interface.encodeFunctionData( - 'appendStateBatch', - [batch, startBlock] - ) - const batchSizeInBytes = remove0x(calldata).length / 2 - this.logger.debug('State batch generated', { - batchSizeInBytes, - calldata, - }) - - if (!this._shouldSubmitBatch(batchSizeInBytes)) { - return - } - - const batchTxBuildEnd = performance.now() - this.metrics.batchTxBuildTime.set(batchTxBuildEnd - batchTxBuildStart) - - const offsetStartsAtIndex = startBlock - this.blockOffset - this.logger.debug('Submitting batch.', { calldata }) - - // Generate the transaction we will repeatedly submit - const nonce = await this.signer.getTransactionCount() - const tx = await this.chainContract.populateTransaction.appendStateBatch( - batch, - offsetStartsAtIndex, - { nonce } - ) - const submitTransaction = (): Promise => { - return this.transactionSubmitter.submitTransaction( - tx, - this._makeHooks('appendStateBatch') - ) - } - return this._submitAndLogTx( - submitTransaction, - 'Submitted state root batch!' - ) - } - - /********************* - * Private Functions * - ********************/ - - private async _generateStateCommitmentBatch( - startBlock: number, - endBlock: number - ): Promise { - const blockRange = endBlock - startBlock - const batch: Bytes32[] = await bPromise.map( - [...Array(blockRange).keys()], - async (i: number) => { - this.logger.debug('Fetching L2BatchElement', { - blockNo: startBlock + i, - }) - const block = (await this.l2Provider.getBlockWithTransactions( - startBlock + i - )) as L2Block - const blockTx = block.transactions[0] - if (blockTx.from === this.fraudSubmissionAddress) { - this.logger.warn('Found transaction from fraud submission address', { - txHash: blockTx.hash, - fraudSubmissionAddress: this.fraudSubmissionAddress, - }) - this.fraudSubmissionAddress = 'no fraud' - return '0xbad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1' - } - return block.stateRoot - }, - { concurrency: 100 } - ) - - let tx = this.chainContract.interface.encodeFunctionData( - 'appendStateBatch', - [batch, startBlock] - ) - while (remove0x(tx).length / 2 > this.maxTxSize) { - batch.splice(Math.ceil((batch.length * 2) / 3)) // Delete 1/3rd of all of the batch elements - this.logger.debug('Splicing batch...', { - batchSizeInBytes: tx.length / 2, - }) - tx = this.chainContract.interface.encodeFunctionData('appendStateBatch', [ - batch, - startBlock, - ]) - } - - this.logger.info('Generated state commitment batch', { - batch, // list of stateRoots - }) - return batch - } -} diff --git a/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts deleted file mode 100644 index 60e73c85d8ae6..0000000000000 --- a/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts +++ /dev/null @@ -1,803 +0,0 @@ -/* External Imports */ -import { performance } from 'perf_hooks' - -import { Promise as bPromise } from 'bluebird' -import { Signer, ethers, Contract, providers } from 'ethers' -import { TransactionReceipt } from '@ethersproject/abstract-provider' -import { getContractInterface, getContractFactory } from 'old-contracts' -import { getContractInterface as getNewContractInterface } from '@eth-optimism/contracts' -import { - L2Block, - RollupInfo, - BatchElement, - Batch, - QueueOrigin, - BatchType, -} from '@eth-optimism/core-utils' -import { Logger, Metrics } from '@eth-optimism/common-ts' - -/* Internal Imports */ -import { - CanonicalTransactionChainContract, - encodeAppendSequencerBatch, - BatchContext, - AppendSequencerBatchParams, -} from '../transaction-chain-contract' -import { TransactionSubmitter } from '../utils' -import { BlockRange, BatchSubmitter } from '.' - -export interface AutoFixBatchOptions { - fixDoublePlayedDeposits: boolean - fixMonotonicity: boolean - fixSkippedDeposits: boolean -} - -export class TransactionBatchSubmitter extends BatchSubmitter { - protected chainContract: CanonicalTransactionChainContract - protected l2ChainId: number - protected syncing: boolean - private autoFixBatchOptions: AutoFixBatchOptions - private validateBatch: boolean - private transactionSubmitter: TransactionSubmitter - private gasThresholdInGwei: number - private batchType: BatchType - - constructor( - signer: Signer, - l2Provider: providers.StaticJsonRpcProvider, - minTxSize: number, - maxTxSize: number, - maxBatchSize: number, - maxBatchSubmissionTime: number, - numConfirmations: number, - resubmissionTimeout: number, - addressManagerAddress: string, - minBalanceEther: number, - gasThresholdInGwei: number, - transactionSubmitter: TransactionSubmitter, - blockOffset: number, - validateBatch: boolean, - logger: Logger, - metrics: Metrics, - autoFixBatchOptions: AutoFixBatchOptions = { - fixDoublePlayedDeposits: false, - fixMonotonicity: false, - fixSkippedDeposits: false, - }, // TODO: Remove this - batchType: string - ) { - super( - signer, - l2Provider, - minTxSize, - maxTxSize, - maxBatchSize, - maxBatchSubmissionTime, - numConfirmations, - resubmissionTimeout, - 0, // Supply dummy value because it is not used. - addressManagerAddress, - minBalanceEther, - blockOffset, - logger, - metrics - ) - this.validateBatch = validateBatch - this.autoFixBatchOptions = autoFixBatchOptions - this.gasThresholdInGwei = gasThresholdInGwei - this.transactionSubmitter = transactionSubmitter - - if (batchType === 'legacy') { - this.batchType = BatchType.LEGACY - } else if (batchType === 'zlib') { - this.batchType = BatchType.ZLIB - } else { - throw new Error(`Invalid batch type: ${batchType}`) - } - - this.logger.info('Batch options', { - autoFixBatchOptions, - validateBatch, - batchType: BatchType[this.batchType], - }) - } - - /***************************** - * Batch Submitter Overrides * - ****************************/ - - public async _updateChainInfo(): Promise { - const info: RollupInfo = await this._getRollupInfo() - if (info.mode === 'verifier') { - this.logger.error( - 'Verifier mode enabled! Batch submitter only compatible with sequencer mode' - ) - process.exit(1) - } - this.syncing = info.syncing - const addrs = await this._getChainAddresses() - const ctcAddress = addrs.ctcAddress - - if ( - typeof this.chainContract !== 'undefined' && - ctcAddress === this.chainContract.address - ) { - this.logger.debug('Chain contract already initialized', { - ctcAddress, - }) - return - } - - const unwrapped_OVM_CanonicalTransactionChain = ( - await getContractFactory('OVM_CanonicalTransactionChain', this.signer) - ).attach(ctcAddress) - - this.chainContract = new CanonicalTransactionChainContract( - unwrapped_OVM_CanonicalTransactionChain.address, - getContractInterface('OVM_CanonicalTransactionChain'), - this.signer - ) - this.logger.info('Initialized new CTC', { - address: this.chainContract.address, - }) - return - } - - public async _onSync(): Promise { - const pendingQueueElements = - await this.chainContract.getNumPendingQueueElements() - this.logger.debug('Got number of pending queue elements', { - pendingQueueElements, - }) - - if (pendingQueueElements !== 0) { - this.logger.info( - 'Syncing mode enabled! Skipping batch submission and clearing queue elements', - { pendingQueueElements } - ) - } - - this.logger.info('Syncing mode enabled but queue is empty. Skipping...') - return - } - - public async _getBatchStartAndEnd(): Promise { - this.logger.info( - 'Getting batch start and end for transaction batch submitter...' - ) - const startBlock = - (await this.chainContract.getTotalElements()).toNumber() + - this.blockOffset - this.logger.info('Retrieved start block number from CTC', { - startBlock, - }) - - const endBlock = - Math.min( - startBlock + this.maxBatchSize, - await this.l2Provider.getBlockNumber() - ) + 1 // +1 because the `endBlock` is *exclusive* - this.logger.info('Retrieved end block number from L2 sequencer', { - endBlock, - }) - - if (startBlock >= endBlock) { - if (startBlock > endBlock) { - this.logger - .error(`More chain elements in L1 (${startBlock}) than in the L2 node (${endBlock}). - This shouldn't happen because we don't submit batches if the sequencer is syncing.`) - } - this.logger.info('No txs to submit. Skipping batch submission...') - return - } - return { - start: startBlock, - end: endBlock, - } - } - - public async _submitBatch( - startBlock: number, - endBlock: number - ): Promise { - // Do not submit batch if gas price above threshold - const gasPriceInGwei = parseInt( - ethers.utils.formatUnits(await this.signer.getGasPrice(), 'gwei'), - 10 - ) - if (gasPriceInGwei > this.gasThresholdInGwei) { - this.logger.warn( - 'Gas price is higher than gas price threshold; aborting batch submission', - { - gasPriceInGwei, - gasThresholdInGwei: this.gasThresholdInGwei, - } - ) - return - } - - const batchTxBuildStart = performance.now() - - const params = await this._generateSequencerBatchParams( - startBlock, - endBlock - ) - if (!params) { - throw new Error( - `Cannot create sequencer batch with params start ${startBlock} and end ${endBlock}` - ) - } - - const [batchParams, wasBatchTruncated] = params - const batchSizeInBytes = encodeAppendSequencerBatch(batchParams).length / 2 - this.logger.debug('Sequencer batch generated', { - batchSizeInBytes, - }) - - // Only submit batch if one of the following is true: - // 1. it was truncated - // 2. it is large enough - // 3. enough time has passed since last submission - if (!wasBatchTruncated && !this._shouldSubmitBatch(batchSizeInBytes)) { - return - } - - const batchTxBuildEnd = performance.now() - this.metrics.batchTxBuildTime.set(batchTxBuildEnd - batchTxBuildStart) - - this.metrics.numTxPerBatch.observe(batchParams.totalElementsToAppend) - const l1tipHeight = await this.signer.provider.getBlockNumber() - this.logger.debug('Submitting batch.', { - calldata: batchParams, - l1tipHeight, - }) - - return this.submitAppendSequencerBatch(batchParams) - } - - /********************* - * Private Functions * - ********************/ - - private async submitAppendSequencerBatch( - batchParams: AppendSequencerBatchParams - ): Promise { - const tx = - await this.chainContract.customPopulateTransaction.appendSequencerBatch( - batchParams - ) - const submitTransaction = (): Promise => { - return this.transactionSubmitter.submitTransaction( - tx, - this._makeHooks('appendSequencerBatch') - ) - } - return this._submitAndLogTx(submitTransaction, 'Submitted batch!') - } - - private async _generateSequencerBatchParams( - startBlock: number, - endBlock: number - ): Promise<[AppendSequencerBatchParams, boolean]> { - // Get all L2 BatchElements for the given range - const blockRange = endBlock - startBlock - let batch: Batch = await bPromise.map( - [...Array(blockRange).keys()], - (i) => { - this.logger.debug('Fetching L2BatchElement', { - blockNo: startBlock + i, - }) - return this._getL2BatchElement(startBlock + i) - }, - { concurrency: 100 } - ) - - // Fix our batches if we are configured to. This will not - // modify the batch unless an autoFixBatchOption is set - batch = await this._fixBatch(batch) - if (this.validateBatch) { - this.logger.info('Validating batch') - if (!(await this._validateBatch(batch))) { - this.metrics.malformedBatches.inc() - return - } - } - - let sequencerBatchParams = await this._getSequencerBatchParams( - startBlock, - batch - ) - - let wasBatchTruncated = false - let encoded = encodeAppendSequencerBatch(sequencerBatchParams) - while (encoded.length / 2 > this.maxTxSize) { - this.logger.debug('Splicing batch...', { - batchSizeInBytes: encoded.length / 2, - }) - batch.splice(Math.ceil((batch.length * 2) / 3)) // Delete 1/3rd of all of the batch elements - sequencerBatchParams = await this._getSequencerBatchParams( - startBlock, - batch - ) - encoded = encodeAppendSequencerBatch(sequencerBatchParams) - // This is to prevent against the case where a batch is oversized, - // but then gets truncated to the point where it is under the minimum size. - // In this case, we want to submit regardless of the batch's size. - wasBatchTruncated = true - } - - // Set the batch type so that it is serialized correctly - sequencerBatchParams.type = this.batchType - - this.logger.info('Generated sequencer batch params', { - contexts: sequencerBatchParams.contexts, - transactions: sequencerBatchParams.transactions, - wasBatchTruncated, - type: BatchType[sequencerBatchParams.type], - }) - return [sequencerBatchParams, wasBatchTruncated] - } - - /** - * Returns true if the batch is valid. - */ - protected async _validateBatch(batch: Batch): Promise { - // Verify all of the queue elements are what we expect - let nextQueueIndex = await this.chainContract.getNextQueueIndex() - for (const ele of batch) { - this.logger.debug('Verifying batch element', { ele }) - if (!ele.isSequencerTx) { - this.logger.debug('Checking queue equality against L1 queue index', { - nextQueueIndex, - }) - if (!(await this._doesQueueElementMatchL1(nextQueueIndex, ele))) { - return false - } - nextQueueIndex++ - } - } - - // Verify all of the batch elements are monotonic - let lastTimestamp: number - let lastBlockNumber: number - for (const [idx, ele] of batch.entries()) { - if (ele.timestamp < lastTimestamp) { - this.logger.error('Timestamp monotonicity violated! Element', { - idx, - ele, - }) - return false - } - if (ele.blockNumber < lastBlockNumber) { - this.logger.error('Block Number monotonicity violated! Element', { - idx, - ele, - }) - return false - } - lastTimestamp = ele.timestamp - lastBlockNumber = ele.blockNumber - } - return true - } - - private async _doesQueueElementMatchL1( - queueIndex: number, - queueElement: BatchElement - ): Promise { - const logEqualityError = (name, index, expected, got) => { - this.logger.error('Observed mismatched values', { - index, - expected, - got, - }) - } - - let isEqual = true - const [, timestamp, blockNumber] = await this.chainContract.getQueueElement( - queueIndex - ) - - // TODO: Verify queue element hash equality. The queue element hash can be computed with: - // keccak256( abi.encode( msg.sender, _target, _gasLimit, _data)) - - // Check timestamp & blockNumber equality - if (timestamp !== queueElement.timestamp) { - isEqual = false - logEqualityError( - 'Timestamp', - queueIndex, - timestamp, - queueElement.timestamp - ) - } - if (blockNumber !== queueElement.blockNumber) { - isEqual = false - logEqualityError( - 'Block Number', - queueIndex, - blockNumber, - queueElement.blockNumber - ) - } - return isEqual - } - - /** - * Takes in a batch which is potentially malformed & returns corrected version. - * Current fixes that are supported: - * - Double played deposits. - */ - private async _fixBatch(batch: Batch): Promise { - const fixDoublePlayedDeposits = async (b: Batch): Promise => { - let nextQueueIndex = await this.chainContract.getNextQueueIndex() - const fixedBatch: Batch = [] - for (const ele of b) { - if (!ele.isSequencerTx) { - if (!(await this._doesQueueElementMatchL1(nextQueueIndex, ele))) { - this.logger.warn('Fixing double played queue element.', { - nextQueueIndex, - }) - fixedBatch.push( - await this._fixDoublePlayedDepositQueueElement( - nextQueueIndex, - ele - ) - ) - continue - } - nextQueueIndex++ - } - fixedBatch.push(ele) - } - return fixedBatch - } - - const fixSkippedDeposits = async (b: Batch): Promise => { - this.logger.debug('Fixing skipped deposits...') - let nextQueueIndex = await this.chainContract.getNextQueueIndex() - const fixedBatch: Batch = [] - for (const ele of b) { - // Look for skipped deposits - while (true) { - const pendingQueueElements = - await this.chainContract.getNumPendingQueueElements() - const nextRemoteQueueElements = - await this.chainContract.getNextQueueIndex() - const totalQueueElements = - pendingQueueElements + nextRemoteQueueElements - // No more queue elements so we clearly haven't skipped anything - if (nextQueueIndex >= totalQueueElements) { - break - } - const [, timestamp, blockNumber] = - await this.chainContract.getQueueElement(nextQueueIndex) - - if (timestamp < ele.timestamp || blockNumber < ele.blockNumber) { - this.logger.warn('Fixing skipped deposit', { - badTimestamp: ele.timestamp, - skippedQueueTimestamp: timestamp, - badBlockNumber: ele.blockNumber, - skippedQueueBlockNumber: blockNumber, - }) - // Push a dummy queue element - fixedBatch.push({ - stateRoot: ele.stateRoot, - isSequencerTx: false, - rawTransaction: undefined, - timestamp, - blockNumber, - }) - nextQueueIndex++ - } else { - // The next queue element's timestamp is after this batch element so - // we must not have skipped anything. - break - } - } - fixedBatch.push(ele) - if (!ele.isSequencerTx) { - nextQueueIndex++ - } - } - return fixedBatch - } - - // TODO: Remove this super complex logic and rely on Geth to actually supply correct block data. - const fixMonotonicity = async (b: Batch): Promise => { - this.logger.debug('Fixing monotonicity...') - // The earliest allowed timestamp/blockNumber is the last timestamp submitted on chain. - const { lastTimestamp, lastBlockNumber } = - await this._getLastTimestampAndBlockNumber() - let earliestTimestamp = lastTimestamp - let earliestBlockNumber = lastBlockNumber - this.logger.debug('Determined earliest timestamp and blockNumber', { - earliestTimestamp, - earliestBlockNumber, - }) - - // The latest allowed timestamp/blockNumber is the next queue element! - let nextQueueIndex = await this.chainContract.getNextQueueIndex() - let latestTimestamp: number - let latestBlockNumber: number - - // updateLatestTimestampAndBlockNumber is a helper which updates - // the latest timestamp and block number based on the pending queue elements. - const updateLatestTimestampAndBlockNumber = async () => { - const pendingQueueElements = - await this.chainContract.getNumPendingQueueElements() - const nextRemoteQueueElements = - await this.chainContract.getNextQueueIndex() - const totalQueueElements = - pendingQueueElements + nextRemoteQueueElements - if (nextQueueIndex < totalQueueElements) { - const [, queueTimestamp, queueBlockNumber] = - await this.chainContract.getQueueElement(nextQueueIndex) - latestTimestamp = queueTimestamp - latestBlockNumber = queueBlockNumber - } else { - // If there are no queue elements left then just allow any timestamp/blocknumber - latestTimestamp = Number.MAX_SAFE_INTEGER - latestBlockNumber = Number.MAX_SAFE_INTEGER - } - } - // Actually update the latest timestamp and block number - await updateLatestTimestampAndBlockNumber() - this.logger.debug('Determined latest timestamp and blockNumber', { - latestTimestamp, - latestBlockNumber, - }) - - // Now go through our batch and fix the timestamps and block numbers - // to automatically enforce monotonicity. - const fixedBatch: Batch = [] - for (const ele of b) { - if (!ele.isSequencerTx) { - // Set the earliest allowed timestamp to the old latest and set the new latest - // to the next queue element's timestamp / blockNumber - earliestTimestamp = latestTimestamp - earliestBlockNumber = latestBlockNumber - nextQueueIndex++ - await updateLatestTimestampAndBlockNumber() - } - // Fix the element if its timestammp/blockNumber is too small - if ( - ele.timestamp < earliestTimestamp || - ele.blockNumber < earliestBlockNumber - ) { - this.logger.warn('Fixing timestamp/blockNumber too small', { - oldTimestamp: ele.timestamp, - newTimestamp: earliestTimestamp, - oldBlockNumber: ele.blockNumber, - newBlockNumber: earliestBlockNumber, - }) - ele.timestamp = earliestTimestamp - ele.blockNumber = earliestBlockNumber - } - // Fix the element if its timestammp/blockNumber is too large - if ( - ele.timestamp > latestTimestamp || - ele.blockNumber > latestBlockNumber - ) { - this.logger.warn('Fixing timestamp/blockNumber too large.', { - oldTimestamp: ele.timestamp, - newTimestamp: latestTimestamp, - oldBlockNumber: ele.blockNumber, - newBlockNumber: latestBlockNumber, - }) - ele.timestamp = latestTimestamp - ele.blockNumber = latestBlockNumber - } - earliestTimestamp = ele.timestamp - earliestBlockNumber = ele.blockNumber - fixedBatch.push(ele) - } - return fixedBatch - } - - // NOTE: It is unsafe to combine multiple autoFix options. - // If you must combine them, manually verify the output before proceeding. - if (this.autoFixBatchOptions.fixDoublePlayedDeposits) { - this.logger.info('Fixing double played deposits') - batch = await fixDoublePlayedDeposits(batch) - } - if (this.autoFixBatchOptions.fixMonotonicity) { - this.logger.info('Fixing monotonicity') - batch = await fixMonotonicity(batch) - } - if (this.autoFixBatchOptions.fixSkippedDeposits) { - this.logger.info('Fixing skipped deposits') - batch = await fixSkippedDeposits(batch) - } - return batch - } - - private async _getLastTimestampAndBlockNumber(): Promise<{ - lastTimestamp: number - lastBlockNumber: number - }> { - const manager = new Contract( - this.addressManagerAddress, - getNewContractInterface('Lib_AddressManager'), - this.signer.provider - ) - - const addr = await manager.getAddress('ChainStorageContainer-CTC-batches') - - const container = new Contract( - addr, - getNewContractInterface('IChainStorageContainer'), - this.signer.provider - ) - - let meta = await container.getGlobalMetadata() - // remove 0x - meta = meta.slice(2) - // convert to bytes27 - meta = meta.slice(10) - - const lastTimestamp = parseInt(meta.slice(-30, -20), 16) - const lastBlockNumber = parseInt(meta.slice(-40, -30), 16) - this.logger.debug('Retrieved timestamp and block number from CTC', { - lastTimestamp, - lastBlockNumber, - }) - - return { lastTimestamp, lastBlockNumber } - } - - private async _fixDoublePlayedDepositQueueElement( - queueIndex: number, - queueElement: BatchElement - ): Promise { - const [, timestamp, blockNumber] = await this.chainContract.getQueueElement( - queueIndex - ) - - if ( - timestamp > queueElement.timestamp && - blockNumber > queueElement.blockNumber - ) { - this.logger.warn( - 'Double deposit detected. Fixing by skipping the deposit & replacing with a dummy tx.', - { - timestamp, - blockNumber, - queueElementTimestamp: queueElement.timestamp, - queueElementBlockNumber: queueElement.blockNumber, - } - ) - const dummyTx: string = '0x1234' - return { - stateRoot: queueElement.stateRoot, - isSequencerTx: true, - rawTransaction: dummyTx, - timestamp: queueElement.timestamp, - blockNumber: queueElement.blockNumber, - } - } - if ( - timestamp < queueElement.timestamp && - blockNumber < queueElement.blockNumber - ) { - this.logger.error('A deposit seems to have been skipped!') - throw new Error('Skipped deposit?!') - } - throw new Error('Unable to fix queue element!') - } - - private async _getSequencerBatchParams( - shouldStartAtIndex: number, - blocks: Batch - ): Promise { - const totalElementsToAppend = blocks.length - - // Generate contexts - const contexts: BatchContext[] = [] - let lastBlockIsSequencerTx = false - let lastTimestamp = 0 - let lastBlockNumber = 0 - const groupedBlocks: Array<{ - sequenced: BatchElement[] - queued: BatchElement[] - }> = [] - for (const block of blocks) { - // Create a new context in certain situations - if ( - // If there are no contexts yet, create a new context. - groupedBlocks.length === 0 || - // If the last block was an L1 to L2 transaction, but the next block is a Sequencer - // transaction, create a new context. - (lastBlockIsSequencerTx === false && block.isSequencerTx === true) || - // If the timestamp of the last block differs from the timestamp of the current block, - // create a new context. Applies to both L1 to L2 transactions and Sequencer transactions. - block.timestamp !== lastTimestamp || - // If the block number of the last block differs from the block number of the current block, - // create a new context. ONLY applies to Sequencer transactions. - (block.blockNumber !== lastBlockNumber && block.isSequencerTx === true) - ) { - groupedBlocks.push({ - sequenced: [], - queued: [], - }) - } - - const cur = groupedBlocks.length - 1 - block.isSequencerTx - ? groupedBlocks[cur].sequenced.push(block) - : groupedBlocks[cur].queued.push(block) - lastBlockIsSequencerTx = block.isSequencerTx - lastTimestamp = block.timestamp - lastBlockNumber = block.blockNumber - } - for (const groupedBlock of groupedBlocks) { - if ( - groupedBlock.sequenced.length === 0 && - groupedBlock.queued.length === 0 - ) { - throw new Error( - 'Attempted to generate batch context with 0 queued and 0 sequenced txs!' - ) - } - contexts.push({ - numSequencedTransactions: groupedBlock.sequenced.length, - numSubsequentQueueTransactions: groupedBlock.queued.length, - timestamp: - groupedBlock.sequenced.length > 0 - ? groupedBlock.sequenced[0].timestamp - : groupedBlock.queued[0].timestamp, - blockNumber: - groupedBlock.sequenced.length > 0 - ? groupedBlock.sequenced[0].blockNumber - : groupedBlock.queued[0].blockNumber, - }) - } - - // Generate sequencer transactions - const transactions: string[] = [] - for (const block of blocks) { - if (!block.isSequencerTx) { - continue - } - transactions.push(block.rawTransaction) - } - - return { - shouldStartAtElement: shouldStartAtIndex - this.blockOffset, - totalElementsToAppend, - contexts, - transactions, - } - } - - private async _getL2BatchElement(blockNumber: number): Promise { - const block = await this._getBlock(blockNumber) - this.logger.debug('Fetched L2 block', { - block, - }) - - const batchElement = { - stateRoot: block.stateRoot, - timestamp: block.timestamp, - blockNumber: block.transactions[0].l1BlockNumber, - isSequencerTx: false, - rawTransaction: undefined, - } - - if (this._isSequencerTx(block)) { - batchElement.isSequencerTx = true - batchElement.rawTransaction = block.transactions[0].rawTransaction - } - - return batchElement - } - - private async _getBlock(blockNumber: number): Promise { - const p = this.l2Provider.getBlockWithTransactions(blockNumber) - return p as Promise - } - - private _isSequencerTx(block: L2Block): boolean { - return block.transactions[0].queueOrigin === QueueOrigin.Sequencer - } -} diff --git a/packages/batch-submitter/src/exec/run-batch-submitter.ts b/packages/batch-submitter/src/exec/run-batch-submitter.ts deleted file mode 100644 index b1184dc553c4e..0000000000000 --- a/packages/batch-submitter/src/exec/run-batch-submitter.ts +++ /dev/null @@ -1,538 +0,0 @@ -/* External Imports */ -import { exit } from 'process' - -import { Bcfg } from '@eth-optimism/core-utils' -import { asL2Provider } from '@eth-optimism/sdk' -import * as Sentry from '@sentry/node' -import { Logger, Metrics, createMetricsServer } from '@eth-optimism/common-ts' -import { Signer, Wallet } from 'ethers' -import { - StaticJsonRpcProvider, - TransactionReceipt, -} from '@ethersproject/providers' -import * as dotenv from 'dotenv' -import Config from 'bcfg' - -/* Internal Imports */ -import { - TransactionBatchSubmitter, - AutoFixBatchOptions, - StateBatchSubmitter, - STATE_BATCH_SUBMITTER_LOG_TAG, - TX_BATCH_SUBMITTER_LOG_TAG, -} from '..' -import { - TransactionSubmitter, - YnatmTransactionSubmitter, - ResubmissionConfig, -} from '../utils' - -interface RequiredEnvVars { - // The HTTP provider URL for L1. - L1_NODE_WEB3_URL: string - // The HTTP provider URL for L2. - L2_NODE_WEB3_URL: string - // The layer one address manager address - ADDRESS_MANAGER_ADDRESS: string - // The minimum size in bytes of any L1 transactions generated by the batch submitter. - MIN_L1_TX_SIZE: number - // The maximum size in bytes of any L1 transactions generated by the batch submitter. - MAX_L1_TX_SIZE: number - // The maximum number of L2 transactions that can ever be in a batch. - MAX_TX_BATCH_COUNT: number - // The maximum number of L2 state roots that can ever be in a batch. - MAX_STATE_BATCH_COUNT: number - // The maximum amount of time (seconds) that we will wait before submitting an under-sized batch. - MAX_BATCH_SUBMISSION_TIME: number - // The delay in milliseconds between querying L2 for more transactions / to create a new batch. - POLL_INTERVAL: number - // The number of confirmations which we will wait after appending new batches. - NUM_CONFIRMATIONS: number - // The number of seconds to wait before resubmitting a transaction. - RESUBMISSION_TIMEOUT: number - // The number of confirmations that we should wait before submitting state roots for CTC elements. - FINALITY_CONFIRMATIONS: number - // Whether or not to run the tx batch submitter. - RUN_TX_BATCH_SUBMITTER: boolean - // Whether or not to run the state batch submitter. - RUN_STATE_BATCH_SUBMITTER: boolean - // The safe minimum amount of ether the batch submitter key should - // hold before it starts to log errors. - SAFE_MINIMUM_ETHER_BALANCE: number - // A boolean to clear the pending transactions in the mempool - // on start up. - CLEAR_PENDING_TXS: boolean -} - -/* Optional Env Vars - * FRAUD_SUBMISSION_ADDRESS - * SEQUENCER_PRIVATE_KEY - * PROPOSER_PRIVATE_KEY - * MNEMONIC - * SEQUENCER_MNEMONIC - * PROPOSER_MNEMONIC - * SEQUENCER_HD_PATH - * PROPOSER_HD_PATH - * BLOCK_OFFSET - * VALIDATE_TX_BATCH - * USE_HARDHAT - * DEBUG_IMPERSONATE_SEQUENCER_ADDRESS - * DEBUG_IMPERSONATE_PROPOSER_ADDRESS - * RUN_METRICS_SERVER - */ - -export const run = async () => { - dotenv.config() - - const config: Bcfg = new Config('batch-submitter') - config.load({ - env: true, - argv: true, - }) - - // Parse config - const env = process.env - const environment = config.str('node-env', env.NODE_ENV) - const network = config.str('eth-network-name', env.ETH_NETWORK_NAME) - const service = `batch-submitter` - const release = `batch-submitter@${env.npm_package_version}` - const sentryDsn = config.str('sentry-dsn', env.SENTRY_DSN) - const sentryTraceRate = config.ufloat( - 'sentry-trace-rate', - parseFloat(env.SENTRY_TRACE_RATE) || 0.05 - ) - - // Default is 1 because Geth normally has 1 more block than L1 - const BLOCK_OFFSET = config.uint( - 'block-offset', - parseInt(env.BLOCK_OFFSET, 10) || 1 - ) - - /* Logger */ - const name = 'oe:batch_submitter:init' - let logger - - if (config.bool('use-sentry', env.USE_SENTRY === 'true')) { - const sentryOptions = { - release, - dsn: sentryDsn, - tracesSampleRate: sentryTraceRate, - environment: network, - } - Sentry.init(sentryOptions) - // Initialize Sentry for Batch Submitter deployed to a network - logger = new Logger({ - name, - sentryOptions, - }) - } else { - // Skip initializing Sentry - logger = new Logger({ name }) - } - - const useHardhat = config.bool('use-hardhat', !!env.USE_HARDHAT) - const DEBUG_IMPERSONATE_SEQUENCER_ADDRESS = config.str( - 'debug-impersonate-sequencer-address', - env.DEBUG_IMPERSONATE_SEQUENCER_ADDRESS - ) - const DEBUG_IMPERSONATE_PROPOSER_ADDRESS = config.str( - 'debug-impersonate-proposer-address', - env.DEBUG_IMPERSONATE_PROPOSER_ADDRESS - ) - - const getSequencerSigner = async (): Promise => { - const l1Provider = new StaticJsonRpcProvider({ - url: requiredEnvVars.L1_NODE_WEB3_URL, - headers: { 'User-Agent': 'batch-submitter' }, - }) - - if (useHardhat) { - if (!DEBUG_IMPERSONATE_SEQUENCER_ADDRESS) { - throw new Error('Must pass DEBUG_IMPERSONATE_SEQUENCER_ADDRESS') - } - await l1Provider.send('hardhat_impersonateAccount', [ - DEBUG_IMPERSONATE_SEQUENCER_ADDRESS, - ]) - return l1Provider.getSigner(DEBUG_IMPERSONATE_SEQUENCER_ADDRESS) - } - - if (SEQUENCER_PRIVATE_KEY) { - return new Wallet(SEQUENCER_PRIVATE_KEY, l1Provider) - } else if (SEQUENCER_MNEMONIC) { - return Wallet.fromMnemonic(SEQUENCER_MNEMONIC, SEQUENCER_HD_PATH).connect( - l1Provider - ) - } - throw new Error( - 'Must pass one of SEQUENCER_PRIVATE_KEY, MNEMONIC, or SEQUENCER_MNEMONIC' - ) - } - - const getProposerSigner = async (): Promise => { - const l1Provider = new StaticJsonRpcProvider({ - url: requiredEnvVars.L1_NODE_WEB3_URL, - headers: { 'User-Agent': 'batch-submitter' }, - }) - - if (useHardhat) { - if (!DEBUG_IMPERSONATE_PROPOSER_ADDRESS) { - throw new Error('Must pass DEBUG_IMPERSONATE_PROPOSER_ADDRESS') - } - await l1Provider.send('hardhat_impersonateAccount', [ - DEBUG_IMPERSONATE_PROPOSER_ADDRESS, - ]) - return l1Provider.getSigner(DEBUG_IMPERSONATE_PROPOSER_ADDRESS) - } - - if (PROPOSER_PRIVATE_KEY) { - return new Wallet(PROPOSER_PRIVATE_KEY, l1Provider) - } else if (PROPOSER_MNEMONIC) { - return Wallet.fromMnemonic(PROPOSER_MNEMONIC, PROPOSER_HD_PATH).connect( - l1Provider - ) - } - throw new Error( - 'Must pass one of PROPOSER_PRIVATE_KEY, MNEMONIC, or PROPOSER_MNEMONIC' - ) - } - - /* Metrics */ - const metrics = new Metrics({ - labels: { environment, release, network, service }, - }) - - const FRAUD_SUBMISSION_ADDRESS = config.str( - 'fraud-submisison-address', - env.FRAUD_SUBMISSION_ADDRESS || 'no fraud' - ) - const MIN_GAS_PRICE_IN_GWEI = config.uint( - 'min-gas-price-in-gwei', - parseInt(env.MIN_GAS_PRICE_IN_GWEI, 10) || 0 - ) - const GAS_RETRY_INCREMENT = config.uint( - 'gas-retry-increment', - parseInt(env.GAS_RETRY_INCREMENT, 10) || 5 - ) - const GAS_THRESHOLD_IN_GWEI = config.uint( - 'gas-threshold-in-gwei', - parseInt(env.GAS_THRESHOLD_IN_GWEI, 10) || 100 - ) - - // Private keys & mnemonics - const SEQUENCER_PRIVATE_KEY = config.str( - 'sequencer-private-key', - env.SEQUENCER_PRIVATE_KEY - ) - // Kept for backwards compatibility - const PROPOSER_PRIVATE_KEY = config.str( - 'proposer-private-key', - env.PROPOSER_PRIVATE_KEY || env.SEQUENCER_PRIVATE_KEY - ) - const SEQUENCER_MNEMONIC = config.str( - 'sequencer-mnemonic', - env.SEQUENCER_MNEMONIC || env.MNEMONIC - ) - const PROPOSER_MNEMONIC = config.str( - 'proposer-mnemonic', - env.PROPOSER_MNEMONIC || env.MNEMONIC - ) - const SEQUENCER_HD_PATH = config.str( - 'sequencer-hd-path', - env.SEQUENCER_HD_PATH || env.HD_PATH - ) - const PROPOSER_HD_PATH = config.str( - 'proposer-hd-path', - env.PROPOSER_HD_PATH || env.HD_PATH - ) - - const VALIDATE_TX_BATCH = config.bool( - 'validate-tx-batch', - env.VALIDATE_TX_BATCH ? env.VALIDATE_TX_BATCH === 'true' : false - ) - - const SEQUENCER_BATCH_TYPE = config.str( - 'sequencer-batch-type', - env.SEQUENCER_BATCH_TYPE || 'legacy' - ) - - // Auto fix batch options -- TODO: Remove this very hacky config - const AUTO_FIX_BATCH_OPTIONS_CONF = config.str( - 'auto-fix-batch-conf', - env.AUTO_FIX_BATCH_OPTIONS_CONF || '' - ) - const autoFixBatchOptions: AutoFixBatchOptions = { - fixDoublePlayedDeposits: AUTO_FIX_BATCH_OPTIONS_CONF - ? AUTO_FIX_BATCH_OPTIONS_CONF.includes('fixDoublePlayedDeposits') - : false, - fixMonotonicity: AUTO_FIX_BATCH_OPTIONS_CONF - ? AUTO_FIX_BATCH_OPTIONS_CONF.includes('fixMonotonicity') - : false, - fixSkippedDeposits: AUTO_FIX_BATCH_OPTIONS_CONF - ? AUTO_FIX_BATCH_OPTIONS_CONF.includes('fixSkippedDeposits') - : false, - } - - logger.info('Starting batch submitter...') - - const requiredEnvVars: RequiredEnvVars = { - L1_NODE_WEB3_URL: config.str('l1-node-web3-url', env.L1_NODE_WEB3_URL), - L2_NODE_WEB3_URL: config.str('l2-node-web3-url', env.L2_NODE_WEB3_URL), - ADDRESS_MANAGER_ADDRESS: config.str( - 'address-manager-address', - env.ADDRESS_MANAGER_ADDRESS - ), - MIN_L1_TX_SIZE: config.uint( - 'min-l1-tx-size', - parseInt(env.MIN_L1_TX_SIZE, 10) - ), - MAX_L1_TX_SIZE: config.uint( - 'max-l1-tx-size', - parseInt(env.MAX_L1_TX_SIZE, 10) - ), - MAX_TX_BATCH_COUNT: config.uint( - 'max-tx-batch-count', - parseInt(env.MAX_TX_BATCH_COUNT, 10) - ), - MAX_STATE_BATCH_COUNT: config.uint( - 'max-state-batch-count', - parseInt(env.MAX_STATE_BATCH_COUNT, 10) - ), - MAX_BATCH_SUBMISSION_TIME: config.uint( - 'max-batch-submisison-time', - parseInt(env.MAX_BATCH_SUBMISSION_TIME, 10) - ), - POLL_INTERVAL: config.uint( - 'poll-interval', - parseInt(env.POLL_INTERVAL, 10) - ), - NUM_CONFIRMATIONS: config.uint( - 'num-confirmations', - parseInt(env.NUM_CONFIRMATIONS, 10) - ), - RESUBMISSION_TIMEOUT: config.uint( - 'resubmission-timeout', - parseInt(env.RESUBMISSION_TIMEOUT, 10) - ), - FINALITY_CONFIRMATIONS: config.uint( - 'finality-confirmations', - parseInt(env.FINALITY_CONFIRMATIONS, 10) - ), - RUN_TX_BATCH_SUBMITTER: config.bool( - 'run-tx-batch-submitter', - env.RUN_TX_BATCH_SUBMITTER === 'true' - ), - RUN_STATE_BATCH_SUBMITTER: config.bool( - 'run-state-batch-submitter', - env.RUN_STATE_BATCH_SUBMITTER === 'true' - ), - SAFE_MINIMUM_ETHER_BALANCE: config.ufloat( - 'safe-minimum-ether-balance', - parseFloat(env.SAFE_MINIMUM_ETHER_BALANCE) - ), - CLEAR_PENDING_TXS: config.bool( - 'clear-pending-txs', - env.CLEAR_PENDING_TXS === 'true' - ), - } - - for (const [key, val] of Object.entries(requiredEnvVars)) { - if (val === null || val === undefined) { - logger.warn('Missing environment variable', { - key, - value: val, - }) - exit(1) - } - } - - if (requiredEnvVars.MIN_L1_TX_SIZE === 0) { - logger.error('Must configure a MIN_L1_TX_SIZE greater than 0') - process.exit(1) - } - - const clearPendingTxs = requiredEnvVars.CLEAR_PENDING_TXS - - const l2Provider = asL2Provider( - new StaticJsonRpcProvider({ - url: requiredEnvVars.L2_NODE_WEB3_URL, - headers: { 'User-Agent': 'batch-submitter' }, - }) - ) - - const sequencerSigner: Signer = await getSequencerSigner() - let proposerSigner: Signer = await getProposerSigner() - - const sequencerAddress = await sequencerSigner.getAddress() - const proposerAddress = await proposerSigner.getAddress() - // If the sequencer & proposer are the same, use a single wallet - if (sequencerAddress === proposerAddress) { - proposerSigner = sequencerSigner - throw new Error( - 'Sequencer and proposer have the same address, multiple transactions may be sent with the same nonce.' - ) - } - - logger.info('Configured batch submitter addresses', { - sequencerAddress, - proposerAddress, - addressManagerAddress: requiredEnvVars.ADDRESS_MANAGER_ADDRESS, - }) - - const resubmissionConfig: ResubmissionConfig = { - resubmissionTimeout: requiredEnvVars.RESUBMISSION_TIMEOUT * 1_000, - minGasPriceInGwei: MIN_GAS_PRICE_IN_GWEI, - maxGasPriceInGwei: GAS_THRESHOLD_IN_GWEI, - gasRetryIncrement: GAS_RETRY_INCREMENT, - } - const txBatchTxSubmitter: TransactionSubmitter = - new YnatmTransactionSubmitter( - sequencerSigner, - resubmissionConfig, - requiredEnvVars.NUM_CONFIRMATIONS - ) - const txBatchSubmitter = new TransactionBatchSubmitter( - sequencerSigner, - l2Provider, - requiredEnvVars.MIN_L1_TX_SIZE, - requiredEnvVars.MAX_L1_TX_SIZE, - requiredEnvVars.MAX_TX_BATCH_COUNT, - requiredEnvVars.MAX_BATCH_SUBMISSION_TIME * 1_000, - requiredEnvVars.NUM_CONFIRMATIONS, - requiredEnvVars.RESUBMISSION_TIMEOUT * 1_000, - requiredEnvVars.ADDRESS_MANAGER_ADDRESS, - requiredEnvVars.SAFE_MINIMUM_ETHER_BALANCE, - GAS_THRESHOLD_IN_GWEI, - txBatchTxSubmitter, - BLOCK_OFFSET, - VALIDATE_TX_BATCH, - logger.child({ name: TX_BATCH_SUBMITTER_LOG_TAG }), - metrics, - autoFixBatchOptions, - SEQUENCER_BATCH_TYPE - ) - - const stateBatchTxSubmitter: TransactionSubmitter = - new YnatmTransactionSubmitter( - proposerSigner, - resubmissionConfig, - requiredEnvVars.NUM_CONFIRMATIONS - ) - const stateBatchSubmitter = new StateBatchSubmitter( - proposerSigner, - l2Provider, - requiredEnvVars.MIN_L1_TX_SIZE, - requiredEnvVars.MAX_L1_TX_SIZE, - requiredEnvVars.MAX_STATE_BATCH_COUNT, - requiredEnvVars.MAX_BATCH_SUBMISSION_TIME * 1_000, - requiredEnvVars.NUM_CONFIRMATIONS, - requiredEnvVars.RESUBMISSION_TIMEOUT * 1_000, - requiredEnvVars.FINALITY_CONFIRMATIONS, - requiredEnvVars.ADDRESS_MANAGER_ADDRESS, - requiredEnvVars.SAFE_MINIMUM_ETHER_BALANCE, - stateBatchTxSubmitter, - BLOCK_OFFSET, - logger.child({ name: STATE_BATCH_SUBMITTER_LOG_TAG }), - metrics, - FRAUD_SUBMISSION_ADDRESS - ) - - // Loops infinitely! - const loop = async ( - func: () => Promise, - signer: Signer - ): Promise => { - // Clear all pending transactions - if (clearPendingTxs) { - try { - const pendingTxs = await signer.getTransactionCount('pending') - const latestTxs = await signer.getTransactionCount('latest') - if (pendingTxs > latestTxs) { - logger.info( - 'Detected pending transactions. Clearing all transactions!' - ) - for (let i = latestTxs; i < pendingTxs; i++) { - const response = await signer.sendTransaction({ - to: await signer.getAddress(), - value: 0, - nonce: i, - }) - logger.info('Submitted empty transaction', { - nonce: i, - txHash: response.hash, - to: response.to, - from: response.from, - }) - logger.debug('empty transaction data', { - data: response.data, - }) - await signer.provider.waitForTransaction( - response.hash, - requiredEnvVars.NUM_CONFIRMATIONS - ) - } - } - } catch (err) { - logger.error('Cannot clear transactions', { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - process.exit(1) - } - } - - while (true) { - try { - await func() - } catch (err) { - switch (err.code) { - case 'SERVER_ERROR': - logger.error(`Encountered server error with status ${err.status}`, { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - break - case 'NETWORK_ERROR': - logger.error('Could not detect network', { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - break - default: - logger.error('Unhandled exception during batch submission', { - message: err.toString(), - stack: err.stack, - code: err.code, - }) - break - } - logger.info('Retrying...') - } - // Sleep - await new Promise((r) => setTimeout(r, requiredEnvVars.POLL_INTERVAL)) - } - } - - // Run batch submitters in two seperate infinite loops! - if (requiredEnvVars.RUN_TX_BATCH_SUBMITTER) { - loop(() => txBatchSubmitter.submitNextBatch(), sequencerSigner) - } - if (requiredEnvVars.RUN_STATE_BATCH_SUBMITTER) { - loop(() => stateBatchSubmitter.submitNextBatch(), proposerSigner) - } - - if (config.bool('run-metrics-server', env.RUN_METRICS_SERVER === 'true')) { - // Initialize metrics server - await createMetricsServer({ - logger, - registry: metrics.registry, - port: config.uint('metrics-port', parseInt(env.METRICS_PORT, 10) || 7300), - hostname: config.str( - 'metrics-hostname', - env.METRICS_HOSTNAME || '127.0.0.1' - ), - }) - } -} diff --git a/packages/batch-submitter/src/index.ts b/packages/batch-submitter/src/index.ts deleted file mode 100644 index 3f90392136db8..0000000000000 --- a/packages/batch-submitter/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './batch-submitter' -export * from './utils' -export * from './transaction-chain-contract' diff --git a/packages/batch-submitter/src/transaction-chain-contract.ts b/packages/batch-submitter/src/transaction-chain-contract.ts deleted file mode 100644 index dde1be08b84ae..0000000000000 --- a/packages/batch-submitter/src/transaction-chain-contract.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* External Imports */ -import { Contract, ethers } from 'ethers' -import { - TransactionResponse, - TransactionRequest, -} from '@ethersproject/abstract-provider' -import { - AppendSequencerBatchParams, - BatchContext, - encodeAppendSequencerBatch, - sequencerBatch, -} from '@eth-optimism/core-utils' - -export { encodeAppendSequencerBatch, BatchContext, AppendSequencerBatchParams } - -/* - * OVM_CanonicalTransactionChainContract is a wrapper around a normal Ethers contract - * where the `appendSequencerBatch(...)` function uses a specialized encoding for improved efficiency. - */ -export class CanonicalTransactionChainContract extends Contract { - public customPopulateTransaction = { - appendSequencerBatch: async ( - batch: AppendSequencerBatchParams - ): Promise => { - const nonce = await this.signer.getTransactionCount() - const to = this.address - const data = getEncodedCalldata(batch) - const gasLimit = await this.signer.provider.estimateGas({ - to, - from: await this.signer.getAddress(), - data, - }) - - return { - nonce, - to, - data, - gasLimit, - } - }, - } - public async appendSequencerBatch( - batch: AppendSequencerBatchParams, - options?: TransactionRequest - ): Promise { - return appendSequencerBatch(this, batch, options) - } -} - -/********************** - * Internal Functions * - *********************/ - -const appendSequencerBatch = async ( - OVM_CanonicalTransactionChain: Contract, - batch: AppendSequencerBatchParams, - options?: TransactionRequest -): Promise => { - return OVM_CanonicalTransactionChain.signer.sendTransaction({ - to: OVM_CanonicalTransactionChain.address, - data: getEncodedCalldata(batch), - ...options, - }) -} - -const getEncodedCalldata = (params: AppendSequencerBatchParams): string => { - return sequencerBatch.encode(params) -} diff --git a/packages/batch-submitter/src/utils/index.ts b/packages/batch-submitter/src/utils/index.ts deleted file mode 100644 index 0913963320f7a..0000000000000 --- a/packages/batch-submitter/src/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './tx-submission' diff --git a/packages/batch-submitter/src/utils/tx-submission.ts b/packages/batch-submitter/src/utils/tx-submission.ts deleted file mode 100644 index f39a8b86c2d08..0000000000000 --- a/packages/batch-submitter/src/utils/tx-submission.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Signer, ethers, PopulatedTransaction } from 'ethers' -import { - TransactionReceipt, - TransactionResponse, -} from '@ethersproject/abstract-provider' -import * as ynatm from '@eth-optimism/ynatm' - -export interface ResubmissionConfig { - resubmissionTimeout: number - minGasPriceInGwei: number - maxGasPriceInGwei: number - gasRetryIncrement: number -} - -export type SubmitTransactionFn = ( - tx: PopulatedTransaction -) => Promise - -export interface TxSubmissionHooks { - beforeSendTransaction: (tx: PopulatedTransaction) => void - onTransactionResponse: (txResponse: TransactionResponse) => void -} - -const getGasPriceInGwei = async (signer: Signer): Promise => { - return parseInt( - ethers.utils.formatUnits(await signer.getGasPrice(), 'gwei'), - 10 - ) -} - -export const ynatmRejectOn = (e) => { - // taken almost verbatim from the readme, - // see https://github.com/ethereum-optimism/ynatm. - // immediately rejects on reverts and nonce errors - const errMsg = e.toString().toLowerCase() - const conditions = ['revert', 'nonce'] - for (const cond of conditions) { - if (errMsg.includes(cond)) { - return true - } - } - - return false -} - -export const submitTransactionWithYNATM = async ( - tx: PopulatedTransaction, - signer: Signer, - config: ResubmissionConfig, - numConfirmations: number, - hooks: TxSubmissionHooks -): Promise => { - const sendTxAndWaitForReceipt = async ( - gasPrice - ): Promise => { - const fullTx = { - ...tx, - gasPrice, - } - hooks.beforeSendTransaction(fullTx) - const txResponse = await signer.sendTransaction(fullTx) - hooks.onTransactionResponse(txResponse) - return signer.provider.waitForTransaction(txResponse.hash, numConfirmations) - } - - const minGasPrice = await getGasPriceInGwei(signer) - const receipt = await ynatm.send({ - sendTransactionFunction: sendTxAndWaitForReceipt, - minGasPrice: ynatm.toGwei(minGasPrice), - maxGasPrice: ynatm.toGwei(config.maxGasPriceInGwei), - gasPriceScalingFunction: ynatm.LINEAR(config.gasRetryIncrement), - delay: config.resubmissionTimeout, - rejectImmediatelyOnCondition: ynatmRejectOn, - }) - return receipt -} - -export interface TransactionSubmitter { - submitTransaction( - tx: PopulatedTransaction, - hooks?: TxSubmissionHooks - ): Promise -} - -export class YnatmTransactionSubmitter implements TransactionSubmitter { - constructor( - readonly signer: Signer, - readonly ynatmConfig: ResubmissionConfig, - readonly numConfirmations: number - ) {} - - public async submitTransaction( - tx: PopulatedTransaction, - hooks?: TxSubmissionHooks - ): Promise { - if (!hooks) { - hooks = { - beforeSendTransaction: () => undefined, - onTransactionResponse: () => undefined, - } - } - return submitTransactionWithYNATM( - tx, - this.signer, - this.ynatmConfig, - this.numConfirmations, - hooks - ) - } -} diff --git a/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts b/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts deleted file mode 100644 index 4d575afd3ac4a..0000000000000 --- a/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts +++ /dev/null @@ -1,475 +0,0 @@ -/* External Imports */ -import { ethers } from 'hardhat' -import '@nomiclabs/hardhat-ethers' -import { Signer, ContractFactory, Contract, BigNumber } from 'ethers' -import sinon from 'sinon' -import scc from '@eth-optimism/contracts/artifacts/contracts/L1/rollup/StateCommitmentChain.sol/StateCommitmentChain.json' -import { getContractInterface } from '@eth-optimism/contracts' -import { smockit, MockContract } from '@eth-optimism/smock' -import { getContractFactory } from 'old-contracts' -import { QueueOrigin, Batch, remove0x } from '@eth-optimism/core-utils' -import { Logger, Metrics } from '@eth-optimism/common-ts' - -/* Internal Imports */ -import { MockchainProvider } from './mockchain-provider' -import { expect } from '../setup' -import { - CanonicalTransactionChainContract, - TransactionBatchSubmitter as RealTransactionBatchSubmitter, - StateBatchSubmitter, - TX_BATCH_SUBMITTER_LOG_TAG, - STATE_BATCH_SUBMITTER_LOG_TAG, - YnatmTransactionSubmitter, - ResubmissionConfig, -} from '../../src' -import { - makeAddressManager, - setProxyTarget, - FORCE_INCLUSION_PERIOD_SECONDS, -} from '../helpers' - -const EXAMPLE_STATE_ROOT = - '0x16b7f83f409c7195b1f4fde5652f1b54a4477eacb6db7927691becafba5f8801' -const MAX_GAS_LIMIT = 8_000_000 -const MAX_TX_SIZE = 100_000 -const MIN_TX_SIZE = 1_000 -const MIN_GAS_PRICE_IN_GWEI = 1 -const GAS_RETRY_INCREMENT = 5 -const GAS_THRESHOLD_IN_GWEI = 120 - -// Helper functions -interface QueueElement { - queueRoot: string - timestamp: number - blockNumber: number -} -const getQueueElement = async ( - ctcContract: Contract, - nextQueueIndex?: number -): Promise => { - if (!nextQueueIndex) { - nextQueueIndex = await ctcContract.getNextQueueIndex() - } - const nextQueueElement = await ctcContract.getQueueElement(nextQueueIndex) - return nextQueueElement -} -// A transaction batch submitter which skips the validate batch check -class TransactionBatchSubmitter extends RealTransactionBatchSubmitter { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected async _validateBatch(batch: Batch): Promise { - return true - } -} -const testMetrics = new Metrics({ prefix: 'bs_test' }) - -describe('BatchSubmitter', () => { - let signer: Signer - let sequencer: Signer - before(async () => { - ;[signer, sequencer] = await ethers.getSigners() - }) - - let AddressManager: Contract - let Mock__OVM_ExecutionManager: MockContract - let Mock__OVM_BondManager: MockContract - let Mock__OVM_StateCommitmentChain: MockContract - before(async () => { - AddressManager = await makeAddressManager() - await AddressManager.setAddress( - 'OVM_Sequencer', - await sequencer.getAddress() - ) - - Mock__OVM_ExecutionManager = await smockit( - await getContractFactory('OVM_ExecutionManager') - ) - - Mock__OVM_BondManager = await smockit( - await getContractFactory('OVM_BondManager') - ) - - Mock__OVM_StateCommitmentChain = await smockit( - await getContractFactory('OVM_StateCommitmentChain') - ) - - await setProxyTarget( - AddressManager, - 'OVM_ExecutionManager', - Mock__OVM_ExecutionManager - ) - - await setProxyTarget( - AddressManager, - 'OVM_BondManager', - Mock__OVM_BondManager - ) - - await setProxyTarget( - AddressManager, - 'OVM_StateCommitmentChain', - Mock__OVM_StateCommitmentChain - ) - - Mock__OVM_StateCommitmentChain.smocked.canOverwrite.will.return.with(false) - Mock__OVM_ExecutionManager.smocked.getMaxTransactionGasLimit.will.return.with( - MAX_GAS_LIMIT - ) - Mock__OVM_BondManager.smocked.isCollateralized.will.return.with(true) - }) - - let Factory__OVM_CanonicalTransactionChain: ContractFactory - let Factory__OVM_StateCommitmentChain: ContractFactory - before(async () => { - Factory__OVM_CanonicalTransactionChain = await getContractFactory( - 'OVM_CanonicalTransactionChain' - ) - - Factory__OVM_CanonicalTransactionChain = - Factory__OVM_CanonicalTransactionChain.connect(signer) - - Factory__OVM_StateCommitmentChain = await getContractFactory( - 'OVM_StateCommitmentChain' - ) - - Factory__OVM_StateCommitmentChain = - Factory__OVM_StateCommitmentChain.connect(signer) - }) - - let OVM_CanonicalTransactionChain: CanonicalTransactionChainContract - let OVM_StateCommitmentChain: Contract - let l2Provider: MockchainProvider - beforeEach(async () => { - const unwrapped_OVM_CanonicalTransactionChain = - await Factory__OVM_CanonicalTransactionChain.deploy( - AddressManager.address, - FORCE_INCLUSION_PERIOD_SECONDS - ) - - await unwrapped_OVM_CanonicalTransactionChain.init() - - await AddressManager.setAddress( - 'OVM_CanonicalTransactionChain', - unwrapped_OVM_CanonicalTransactionChain.address - ) - - await AddressManager.setAddress( - 'CanonicalTransactionChain', - unwrapped_OVM_CanonicalTransactionChain.address - ) - - OVM_CanonicalTransactionChain = new CanonicalTransactionChainContract( - unwrapped_OVM_CanonicalTransactionChain.address, - getContractInterface('CanonicalTransactionChain'), - sequencer - ) - - const unwrapped_OVM_StateCommitmentChain = - await Factory__OVM_StateCommitmentChain.deploy( - AddressManager.address, - 0, // fraudProofWindowSeconds - 0 // sequencerPublishWindowSeconds - ) - - await unwrapped_OVM_StateCommitmentChain.init() - - await AddressManager.setAddress( - 'OVM_StateCommitmentChain', - unwrapped_OVM_StateCommitmentChain.address - ) - - await AddressManager.setAddress( - 'StateCommitmentChain', - unwrapped_OVM_StateCommitmentChain.address - ) - - OVM_StateCommitmentChain = new Contract( - unwrapped_OVM_StateCommitmentChain.address, - getContractInterface('StateCommitmentChain'), - sequencer - ) - - l2Provider = new MockchainProvider( - OVM_CanonicalTransactionChain.address, - OVM_StateCommitmentChain.address - ) - }) - - afterEach(() => { - sinon.restore() - }) - - const createBatchSubmitter = (timeout: number): TransactionBatchSubmitter => { - const resubmissionConfig: ResubmissionConfig = { - resubmissionTimeout: 100000, - minGasPriceInGwei: MIN_GAS_PRICE_IN_GWEI, - maxGasPriceInGwei: GAS_THRESHOLD_IN_GWEI, - gasRetryIncrement: GAS_RETRY_INCREMENT, - } - const txBatchTxSubmitter = new YnatmTransactionSubmitter( - sequencer, - resubmissionConfig, - 1 - ) - return new TransactionBatchSubmitter( - sequencer, - l2Provider as any, - MIN_TX_SIZE, - MAX_TX_SIZE, - 10, - timeout, - 1, - 100000, - AddressManager.address, - 1, - GAS_THRESHOLD_IN_GWEI, - txBatchTxSubmitter, - 1, - false, - new Logger({ name: TX_BATCH_SUBMITTER_LOG_TAG }), - testMetrics, - { - fixDoublePlayedDeposits: false, - fixMonotonicity: false, - fixSkippedDeposits: false, - }, - 'legacy' - ) - } - - describe('TransactionBatchSubmitter', () => { - describe('submitNextBatch', () => { - let batchSubmitter - beforeEach(async () => { - for (let i = 1; i < 15; i++) { - await OVM_CanonicalTransactionChain.enqueue( - '0x' + '01'.repeat(20), - 50_000, - '0x' + i.toString().repeat(64), - { - gasLimit: 1_000_000, - } - ) - } - batchSubmitter = createBatchSubmitter(0) - }) - - it('should submit a sequencer batch correctly', async () => { - l2Provider.setNumBlocksToReturn(5) - const nextQueueElement = await getQueueElement( - OVM_CanonicalTransactionChain - ) - l2Provider.setL2BlockData( - { - rawTransaction: '0x1234', - l1BlockNumber: nextQueueElement.blockNumber - 1, - txType: 0, - queueOrigin: QueueOrigin.Sequencer, - l1TxOrigin: null, - } as any, - nextQueueElement.timestamp - 1 - ) - let receipt = await batchSubmitter.submitNextBatch() - let logData = remove0x(receipt.logs[1].data) - expect(parseInt(logData.slice(64 * 0, 64 * 1), 16)).to.equal(0) // _startingQueueIndex - expect(parseInt(logData.slice(64 * 1, 64 * 2), 16)).to.equal(0) // _numQueueElements - expect(parseInt(logData.slice(64 * 2, 64 * 3), 16)).to.equal(6) // _totalElements - receipt = await batchSubmitter.submitNextBatch() - logData = remove0x(receipt.logs[1].data) - expect(parseInt(logData.slice(64 * 0, 64 * 1), 16)).to.equal(0) // _startingQueueIndex - expect(parseInt(logData.slice(64 * 1, 64 * 2), 16)).to.equal(0) // _numQueueElements - expect(parseInt(logData.slice(64 * 2, 64 * 3), 16)).to.equal(11) // _totalElements - }) - - it('should submit a queue batch correctly', async () => { - l2Provider.setNumBlocksToReturn(5) - l2Provider.setL2BlockData({ - queueOrigin: QueueOrigin.L1ToL2, - } as any) - let receipt = await batchSubmitter.submitNextBatch() - let logData = remove0x(receipt.logs[1].data) - expect(parseInt(logData.slice(64 * 0, 64 * 1), 16)).to.equal(0) // _startingQueueIndex - expect(parseInt(logData.slice(64 * 1, 64 * 2), 16)).to.equal(6) // _numQueueElements - expect(parseInt(logData.slice(64 * 2, 64 * 3), 16)).to.equal(6) // _totalElements - receipt = await batchSubmitter.submitNextBatch() - logData = remove0x(receipt.logs[1].data) - expect(parseInt(logData.slice(64 * 0, 64 * 1), 16)).to.equal(6) // _startingQueueIndex - expect(parseInt(logData.slice(64 * 1, 64 * 2), 16)).to.equal(5) // _numQueueElements - expect(parseInt(logData.slice(64 * 2, 64 * 3), 16)).to.equal(11) // _totalElements - }) - - it('should submit a batch with both queue and sequencer chain elements', async () => { - l2Provider.setNumBlocksToReturn(10) // For this batch we'll return 10 elements! - l2Provider.setL2BlockData({ - queueOrigin: QueueOrigin.L1ToL2, - } as any) - // Turn blocks 3-5 into sequencer txs - const nextQueueElement = await getQueueElement( - OVM_CanonicalTransactionChain, - 2 - ) - l2Provider.setL2BlockData( - { - rawTransaction: '0x1234', - l1BlockNumber: nextQueueElement.blockNumber - 1, - txType: 1, - queueOrigin: QueueOrigin.Sequencer, - l1TxOrigin: null, - } as any, - nextQueueElement.timestamp - 1, - '', // blank stateRoot - 3, - 6 - ) - const receipt = await batchSubmitter.submitNextBatch() - const logData = remove0x(receipt.logs[1].data) - expect(parseInt(logData.slice(64 * 0, 64 * 1), 16)).to.equal(0) // _startingQueueIndex - expect(parseInt(logData.slice(64 * 1, 64 * 2), 16)).to.equal(8) // _numQueueElements - expect(parseInt(logData.slice(64 * 2, 64 * 3), 16)).to.equal(11) // _totalElements - }) - - it('should submit a small batch only after the timeout', async () => { - l2Provider.setNumBlocksToReturn(2) - l2Provider.setL2BlockData({ - queueOrigin: QueueOrigin.L1ToL2, - } as any) - - // Create a batch submitter with a long timeout & make sure it doesn't submit the batches one after another - const longTimeout = 10_000 - batchSubmitter = createBatchSubmitter(longTimeout) - let receipt = await batchSubmitter.submitNextBatch() - expect(receipt).to.not.be.undefined - receipt = await batchSubmitter.submitNextBatch() - // The receipt should be undefined because that means it didn't submit - expect(receipt).to.be.undefined - - // This time create a batch submitter with a short timeout & it should submit batches after the timeout is reached - const shortTimeout = 5 - batchSubmitter = createBatchSubmitter(shortTimeout) - receipt = await batchSubmitter.submitNextBatch() - expect(receipt).to.not.be.undefined - // Sleep for the short timeout - await new Promise((r) => setTimeout(r, shortTimeout)) - receipt = await batchSubmitter.submitNextBatch() - // The receipt should NOT be undefined because that means it successfully submitted! - expect(receipt).to.not.be.undefined - }) - - it('should not submit if gas price is over threshold', async () => { - l2Provider.setNumBlocksToReturn(2) - l2Provider.setL2BlockData({ - queueOrigin: QueueOrigin.L1ToL2, - } as any) - - const highGasPriceWei = BigNumber.from(200).mul(1_000_000_000) - - sinon - .stub(sequencer, 'getGasPrice') - .callsFake(async () => highGasPriceWei) - - const receipt = await batchSubmitter.submitNextBatch() - expect(sequencer.getGasPrice).to.have.been.calledOnce - expect(receipt).to.be.undefined - }) - - it('should submit if gas price is not over threshold', async () => { - l2Provider.setNumBlocksToReturn(2) - l2Provider.setL2BlockData({ - queueOrigin: QueueOrigin.L1ToL2, - } as any) - - const lowGasPriceWei = BigNumber.from(2).mul(1_000_000_000) - - sinon - .stub(sequencer, 'getGasPrice') - .callsFake(async () => lowGasPriceWei) - - const receipt = await batchSubmitter.submitNextBatch() - expect(sequencer.getGasPrice).to.have.been.calledTwice - expect(receipt).to.not.be.undefined - }) - }) - }) - - describe('StateBatchSubmitter', () => { - let txBatchSubmitter - let stateBatchSubmitter - beforeEach(async () => { - for (let i = 1; i < 15; i++) { - await OVM_CanonicalTransactionChain.enqueue( - '0x' + '01'.repeat(20), - 50_000, - '0x' + i.toString().repeat(64), - { - gasLimit: 1_000_000, - } - ) - } - - txBatchSubmitter = createBatchSubmitter(0) - - l2Provider.setNumBlocksToReturn(5) - const nextQueueElement = await getQueueElement( - OVM_CanonicalTransactionChain - ) - l2Provider.setL2BlockData( - { - rawTransaction: '0x1234', - l1BlockNumber: nextQueueElement.blockNumber - 1, - txType: 0, - queueOrigin: QueueOrigin.Sequencer, - l1TxOrigin: null, - } as any, - nextQueueElement.timestamp - 1, - EXAMPLE_STATE_ROOT // example stateRoot - ) - - // submit a batch of transactions to enable state batch submission - await txBatchSubmitter.submitNextBatch() - - const resubmissionConfig: ResubmissionConfig = { - resubmissionTimeout: 100000, - minGasPriceInGwei: MIN_GAS_PRICE_IN_GWEI, - maxGasPriceInGwei: GAS_THRESHOLD_IN_GWEI, - gasRetryIncrement: GAS_RETRY_INCREMENT, - } - const stateBatchTxSubmitter = new YnatmTransactionSubmitter( - sequencer, - resubmissionConfig, - 1 - ) - stateBatchSubmitter = new StateBatchSubmitter( - sequencer, - l2Provider as any, - MIN_TX_SIZE, - MAX_TX_SIZE, - 10, // maxBatchSize - 0, - 1, - 100000, - 0, // finalityConfirmations - AddressManager.address, - 1, - stateBatchTxSubmitter, - 1, - new Logger({ name: STATE_BATCH_SUBMITTER_LOG_TAG }), - testMetrics, - '0x' + '01'.repeat(20) // placeholder for fraudSubmissionAddress - ) - }) - - describe('submitNextBatch', () => { - it('should submit a state batch after a transaction batch', async () => { - const receipt = await stateBatchSubmitter.submitNextBatch() - expect(receipt).to.not.be.undefined - - const iface = new ethers.utils.Interface(scc.abi) - const parsedLogs = iface.parseLog(receipt.logs[0]) - - expect(parsedLogs.eventFragment.name).to.eq('StateBatchAppended') - expect(parsedLogs.args._batchIndex.toNumber()).to.eq(0) - expect(parsedLogs.args._batchSize.toNumber()).to.eq(6) - expect(parsedLogs.args._prevTotalElements.toNumber()).to.eq(0) - }) - }) - }) -}) diff --git a/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts b/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts deleted file mode 100644 index d936daf9c77da..0000000000000 --- a/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts +++ /dev/null @@ -1,966 +0,0 @@ -/* External Imports */ -import { providers, BigNumber } from 'ethers' -import { - BlockWithTransactions, - TransactionResponse, -} from '@ethersproject/abstract-provider' -import { L2Transaction, L2Block, RollupInfo } from '@eth-optimism/core-utils' - -/** - * Unformatted Transaction & Blocks. This exists because Geth currently - * does not return the correct fields & so this code renames those - * poorly named fields - */ -interface UnformattedL2Transaction extends TransactionResponse { - l1BlockNumber: string - l1MessageSender: string - signatureHashType: string - queueOrigin: string - rawTransaction: string -} - -interface UnformattedL2Block extends BlockWithTransactions { - stateRoot: string - transactions: [UnformattedL2Transaction] -} - -export class MockchainProvider extends providers.JsonRpcProvider { - public mockBlockNumber: number = 1 - public numBlocksToReturn: number = 2 - public mockBlocks: L2Block[] = [] - public ctcAddr: string - public sccAddr: string - - constructor(ctcAddr: string, sccAddr: string) { - super('https://optimism.io') - for (const block of BLOCKS) { - if (block.number === 0) { - // No need to convert genesis to an L2Block because it has no txs - this.mockBlocks.push(block) - continue - } - this.mockBlocks.push(this._toL2Block(block)) - this.ctcAddr = ctcAddr - this.sccAddr = sccAddr - } - } - - public async getBlockNumber(): Promise { - // Increment our mock block number every time - if ( - this.mockBlockNumber + this.numBlocksToReturn < - this.mockBlocks.length - ) { - this.mockBlockNumber += this.numBlocksToReturn - } else { - return this.mockBlocks.length - 1 - } - return this.mockBlockNumber - } - - public async send(endpoint: string, params: []): Promise { - switch (endpoint) { - case 'eth_chainId': - return this.chainId() - case 'rollup_getInfo': - const info: RollupInfo = { - mode: 'sequencer', - syncing: false, - ethContext: { - timestamp: 0, - blockNumber: 0, - }, - rollupContext: { - index: 0, - queueIndex: 0, - }, - } - return info - case 'eth_getBlockByNumber': - if (params.length === 0) { - throw new Error(`Invalid params for ${endpoint}`) - } - const blockNumber = BigNumber.from((params as any)[0]).toNumber() - return this.mockBlocks[blockNumber] - default: - throw new Error('Unsupported endpoint!') - } - } - - public setNumBlocksToReturn(numBlocks: number): void { - this.numBlocksToReturn = numBlocks - } - - public setL2BlockData( - tx: L2Transaction, - timestamp?: number, - stateRoot?: string, - start: number = 1, - end: number = this.mockBlocks.length - ) { - for (let i = start; i < end; i++) { - this.mockBlocks[i].timestamp = timestamp - ? timestamp - : this.mockBlocks[i].timestamp - this.mockBlocks[i].transactions[0] = { - ...this.mockBlocks[i].transactions[0], - ...tx, - } - this.mockBlocks[i].stateRoot = stateRoot - } - } - - public async getBlockWithTransactions(blockNumber: number): Promise { - return this.mockBlocks[blockNumber] - } - - public chainId(): number { - // We know that mockBlocks will always have at least 1 value - return this.mockBlocks[1].transactions[0].chainId - } - - private _toL2Block(block: UnformattedL2Block): L2Block { - const l1BlockNumber: number = parseInt( - block.transactions[0].l1BlockNumber, - 10 - ) - const queueOrigin: string = block.transactions[0].queueOrigin - const l1TxOrigin: string = block.transactions[0].l1MessageSender - const l2Transaction: L2Transaction = { - ...block.transactions[0], - // Rename the incorrectly named fields - l1TxOrigin, - queueOrigin, - l1BlockNumber, - } - // Add an interface here to fix the type casing into L2Block during Object.assign - interface PartialL2Block { - transactions: [L2Transaction] - } - const partialBlock: PartialL2Block = { - transactions: [l2Transaction], - } - const l2Block: L2Block = { ...block, ...partialBlock } - return l2Block - } -} - -const BLOCKS = JSON.parse(` -[ - { - "hash":"0xbc27fdbd1fee6e001438709ef57210bb7b2b1b8c23b65acb2d79161f4dc3cf05", - "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", - "number":0, - "timestamp":1603651804, - "nonce":"0x0000000000000042", - "difficulty":1, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0x0000000000000000000000000000000000000000", - "extraData":"0x1234", - "transactions":[ - ] - }, - { - "hash":"0x05a7f5c5fce57346f59355184daa58822f97a32e4327fe6ef4a1c37dfd36f2f0", - "parentHash":"0x64e89492b3ea72b9f9f0f4566e5198e19d7bfa583619c54c33872c7112aec9cd", - "number":1, - "timestamp":1603404102, - "nonce":"0x0000000000000042", - "difficulty":131072, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x688ddd1acc3cbccd9112018eac6c78744f43140d408128b8ed0392c7ee28966e", - "blockHash":"0x05a7f5c5fce57346f59355184daa58822f97a32e4327fe6ef4a1c37dfd36f2f0", - "blockNumber":1, - "transactionIndex":0, - "confirmations":16, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x05bc67" - }, - "to":null, - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":0, - "data":"0x608060405234801561001057600080fd5b50600080546001600160a01b03191633178082556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a361056a806100696000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063715018a61461005c5780638da5cb5b146100665780639b2ea4bd1461008a578063bf40fac11461013b578063f2fde38b146101e1575b600080fd5b610064610207565b005b61006e6102b0565b604080516001600160a01b039092168252519081900360200190f35b610064600480360360408110156100a057600080fd5b8101906020810181356401000000008111156100bb57600080fd5b8201836020820111156100cd57600080fd5b803590602001918460018302840111640100000000831117156100ef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031691506102bf9050565b61006e6004803603602081101561015157600080fd5b81019060208101813564010000000081111561016c57600080fd5b82018360208201111561017e57600080fd5b803590602001918460018302840111640100000000831117156101a057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610362945050505050565b610064600480360360208110156101f757600080fd5b50356001600160a01b0316610391565b6000546001600160a01b03163314610266576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031681565b6000546001600160a01b0316331461031e576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b806001600061032c85610490565b815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b60006001600061037184610490565b81526020810191909152604001600020546001600160a01b031692915050565b6000546001600160a01b031633146103f0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166104355760405162461bcd60e51b815260040180806020018281038252602d815260200180610508602d913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000816040516020018082805190602001908083835b602083106104c55780518252601f1990920191602091820191016104a6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905091905056fe4f776e61626c653a206e6577206f776e65722063616e6e6f7420626520746865207a65726f2061646472657373a26469706673582212204367ffc2e6671623708150e2d0cff4c12cf566722a26b4748555d789953e2d2264736f6c63430007000033", - "r":"0x2babe370e2e422a38386a5a96cd3bf16772ddbbf8c9dab8aadf4416fff557756", - "s":"0x213ab994b50ed4a38e2de390f851d88cb66dd238a27d89246616b34eb8e859df", - "v":62710, - "creates":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0xb5903854b196abb9b7d1e3c2f5f8f9519b4fedefc21d72f3d92c74f128afcd46", - "parentHash":"0x05a7f5c5fce57346f59355184daa58822f97a32e4327fe6ef4a1c37dfd36f2f0", - "number":2, - "timestamp":1603404103, - "nonce":"0x0000000000000042", - "difficulty":131136, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0xeae52be001bfea0b3d8de2de5edff5c0c39d26f6e6ab0fc6623cd24913dbf150", - "blockHash":"0xb5903854b196abb9b7d1e3c2f5f8f9519b4fedefc21d72f3d92c74f128afcd46", - "blockNumber":2, - "transactionIndex":0, - "confirmations":15, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xaeab" - }, - "to":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":1, - "data":"0x9b2ea4bd000000000000000000000000000000000000000000000000000000000000004000000000000000000000000063fc2ad3d021a4d7e64323529a55a9442c444da0000000000000000000000000000000000000000000000000000000000000000d4f564d5f53657175656e63657200000000000000000000000000000000000000", - "r":"0x530be666add21a30fe9a0fadee8072d4d8ccb2b80a9fe07c7e0591c5a1e5f375", - "s":"0x5954b17cd0f6299ee54f20853bcfdfc870f2fc271f0433fd592b8b0fc0329aa4", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x7504e7104a2d80e810758c1cc2736028ffe5632a2ec988da740c93b3cfa03945", - "parentHash":"0xb5903854b196abb9b7d1e3c2f5f8f9519b4fedefc21d72f3d92c74f128afcd46", - "number":3, - "timestamp":1603404104, - "nonce":"0x0000000000000042", - "difficulty":131200, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x79f4dc191018a37a8b71b4a5aff02ce501b0341fc72708c8095845e61be15c02", - "blockHash":"0x7504e7104a2d80e810758c1cc2736028ffe5632a2ec988da740c93b3cfa03945", - "blockNumber":3, - "transactionIndex":0, - "confirmations":14, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xafb0" - }, - "to":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":2, - "data":"0x9b2ea4bd0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000420000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000224f564d5f4465636f6d7072657373696f6e507265636f6d70696c6541646472657373000000000000000000000000000000000000000000000000000000000000", - "r":"0x388b6b7e4fe10128e92507042971b864edd535d8f3cb70c61247daed1dc734c1", - "s":"0x6ad11366b26fa59ce73bc73fa320560f46ffb6df3142adbd16ebce0bcc3ba9f5", - "v":62710, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x6587aa5da64944673741bdd3299c0d2471c2fdbfcd94713d511ab7240d127bbb", - "parentHash":"0x7504e7104a2d80e810758c1cc2736028ffe5632a2ec988da740c93b3cfa03945", - "number":4, - "timestamp":1603404105, - "nonce":"0x0000000000000042", - "difficulty":131264, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x0584fbd34096ffc0fc96dbdf1d8ee574c3eda9e07bf85aed9862542416b1a007", - "blockHash":"0x6587aa5da64944673741bdd3299c0d2471c2fdbfcd94713d511ab7240d127bbb", - "blockNumber":4, - "transactionIndex":0, - "confirmations":13, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02e294" - }, - "to":null, - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":3, - "data":"0x608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610213806100326000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063776d1a0114610077575b60015460408051602036601f8101829004820283018201909352828252610075936001600160a01b0316926000918190840183828082843760009201919091525061009d92505050565b005b6100756004803603602081101561008d57600080fd5b50356001600160a01b031661015d565b60006060836001600160a01b0316836040518082805190602001908083835b602083106100db5780518252601f1990920191602091820191016100bc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461013d576040519150601f19603f3d011682016040523d82523d6000602084013e610142565b606091505b5091509150811561015557805160208201f35b805160208201fd5b6000546001600160a01b031633141561019057600180546001600160a01b0319166001600160a01b0383161790556101da565b60015460408051602036601f81018290048202830182019093528282526101da936001600160a01b0316926000918190840183828082843760009201919091525061009d92505050565b5056fea2646970667358221220293887d48c4c1c34de868edf3e9a6be82327946c76d71f7c2023e67f556c6ecb64736f6c63430007000033", - "r":"0x2e420851664bb81c0d5d0bd1a805661fc1f83922b92e1d9e0e57c9184eddec0e", - "s":"0x5e00184c9b50ed54e714231af904caed92cf47ee309fc3604793d7d32a9f4988", - "v":62709, - "creates":"0x94BA4d5Ebb0e05A50e977FFbF6e1a1Ee3D89299c", - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x7a215669ab018e508473ef76b42d19cc4228cc5cc855089dc04cb22555fcf555", - "parentHash":"0x6587aa5da64944673741bdd3299c0d2471c2fdbfcd94713d511ab7240d127bbb", - "number":5, - "timestamp":1603404106, - "nonce":"0x0000000000000042", - "difficulty":131328, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0xc8243d8b9bf79624f8930527a983be3581cb7d969ae76d3e5962f9db2be7b71a", - "blockHash":"0x7a215669ab018e508473ef76b42d19cc4228cc5cc855089dc04cb22555fcf555", - "blockNumber":5, - "transactionIndex":0, - "confirmations":12, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xa93c" - }, - "to":"0x94BA4d5Ebb0e05A50e977FFbF6e1a1Ee3D89299c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":4, - "data":"0x776d1a01000000000000000000000000e9a9a643588daa154de182f88a5b04e8745909c2", - "r":"0x2de73fc5aec124cc9cf0fa54fc8492692a48b8921a32d31f46f5d431fdeea7a0", - "s":"0x4e813ae50bc7705fb023d79429ed6cc92367cb5209460e6ea3904c014b06cd4d", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0xb4c01e6e867856dce9b451ba67273f86bdc584ff398ed5b8c46f70ea37b1002f", - "parentHash":"0x7a215669ab018e508473ef76b42d19cc4228cc5cc855089dc04cb22555fcf555", - "number":6, - "timestamp":1603404107, - "nonce":"0x0000000000000042", - "difficulty":131392, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0xa5bf13c2638f1d99a26c4c7d867f1bc64a34ebf141524b35840c879536e69d69", - "blockHash":"0xb4c01e6e867856dce9b451ba67273f86bdc584ff398ed5b8c46f70ea37b1002f", - "blockNumber":6, - "transactionIndex":0, - "confirmations":11, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xaeff" - }, - "to":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":5, - "data":"0x9b2ea4bd000000000000000000000000000000000000000000000000000000000000004000000000000000000000000094ba4d5ebb0e05a50e977ffbf6e1a1ee3d89299c00000000000000000000000000000000000000000000000000000000000000144f564d5f457865637574696f6e4d616e61676572000000000000000000000000", - "r":"0x42a7ca8603050e58d948df4573374746fabc8542c3fabc1d3b03391c2e50ae3b", - "s":"0x99b52df93bddbd15393ec9b6649c569ec9f65b1e7dda62b7a81baf32bd951a36", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x9f8a3aae03d0f8f769d5af64583c1ee32458bd5b63bf6436147e624ef3297c69", - "parentHash":"0xb4c01e6e867856dce9b451ba67273f86bdc584ff398ed5b8c46f70ea37b1002f", - "number":7, - "timestamp":1603404108, - "nonce":"0x0000000000000042", - "difficulty":131456, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x967c90bfcb19090f0b73b0d0ca4d5f866160d7628d84412fada18abc50e3da69", - "blockHash":"0x9f8a3aae03d0f8f769d5af64583c1ee32458bd5b63bf6436147e624ef3297c69", - "blockNumber":7, - "transactionIndex":0, - "confirmations":10, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02e294" - }, - "to":null, - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":6, - "data":"0x608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610213806100326000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063776d1a0114610077575b60015460408051602036601f8101829004820283018201909352828252610075936001600160a01b0316926000918190840183828082843760009201919091525061009d92505050565b005b6100756004803603602081101561008d57600080fd5b50356001600160a01b031661015d565b60006060836001600160a01b0316836040518082805190602001908083835b602083106100db5780518252601f1990920191602091820191016100bc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461013d576040519150601f19603f3d011682016040523d82523d6000602084013e610142565b606091505b5091509150811561015557805160208201f35b805160208201fd5b6000546001600160a01b031633141561019057600180546001600160a01b0319166001600160a01b0383161790556101da565b60015460408051602036601f81018290048202830182019093528282526101da936001600160a01b0316926000918190840183828082843760009201919091525061009d92505050565b5056fea2646970667358221220293887d48c4c1c34de868edf3e9a6be82327946c76d71f7c2023e67f556c6ecb64736f6c63430007000033", - "r":"0x16f49916bda30884d49df7f83c60ca49899fd21311e4cd4b464ac52bfa722b40", - "s":"0x3a2873207cbcba218ff71bb7e3916ea809c393c2407c03a70bbf4e393cbebfcb", - "v":62709, - "creates":"0x956dA338C1518a7FB213042b70c60c021aeBd554", - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x808315e40a80d00bf171b8ba924b451fb7936d446177c9e3545303b2ef830801", - "parentHash":"0x9f8a3aae03d0f8f769d5af64583c1ee32458bd5b63bf6436147e624ef3297c69", - "number":8, - "timestamp":1603404109, - "nonce":"0x0000000000000042", - "difficulty":131520, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x3dabdb84873e50c3b26df28ead1c053451a340b20d945a8cf8bddf5b5ff11775", - "blockHash":"0x808315e40a80d00bf171b8ba924b451fb7936d446177c9e3545303b2ef830801", - "blockNumber":8, - "transactionIndex":0, - "confirmations":9, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xa93c" - }, - "to":"0x956dA338C1518a7FB213042b70c60c021aeBd554", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":7, - "data":"0x776d1a01000000000000000000000000048b45c16e9631d3f630106c6086ec21a30cdf60", - "r":"0x553525e3656dfb41299a9f2a0d1a0058445e017bb98992de6d9b762203cf975a", - "s":"0x74b9f344513fa2881cfcec5a4c20027bb905de5c52a8e584da6767d946cd465d", - "v":62710, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0xed13ac7f6bf594309a325c1558e4a3032f745e66ee0ffc2f95a701562b53dd13", - "parentHash":"0x808315e40a80d00bf171b8ba924b451fb7936d446177c9e3545303b2ef830801", - "number":9, - "timestamp":1603404110, - "nonce":"0x0000000000000042", - "difficulty":131584, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x2b9e216b390804c731f3ffc0630e522865bff35d0c539f377d204e94a346eddd", - "blockHash":"0xed13ac7f6bf594309a325c1558e4a3032f745e66ee0ffc2f95a701562b53dd13", - "blockNumber":9, - "transactionIndex":0, - "confirmations":8, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0xaf2f" - }, - "to":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":8, - "data":"0x9b2ea4bd0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000956da338c1518a7fb213042b70c60c021aebd55400000000000000000000000000000000000000000000000000000000000000184f564d5f5374617465436f6d6d69746d656e74436861696e0000000000000000", - "r":"0x6318ce7714d7aefc9add30ebcf9d657a01b50c308c689c6f7d5567d806b6914e", - "s":"0xfe4d90d895f4b18b89309d768a383334bf5d622d367051079ac0e401b23960e0", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x65f3831f69d1e746f30d07a3def1eefdcc6650ee0714cbac795c2be3ce9430a2", - "parentHash":"0xed13ac7f6bf594309a325c1558e4a3032f745e66ee0ffc2f95a701562b53dd13", - "number":10, - "timestamp":1603404111, - "nonce":"0x0000000000000042", - "difficulty":131648, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0xa77aca829b5bc91a16c11efb4dee280345851fccbd83b1469f746349894a46ab", - "blockHash":"0x65f3831f69d1e746f30d07a3def1eefdcc6650ee0714cbac795c2be3ce9430a2", - "blockNumber":10, - "transactionIndex":0, - "confirmations":7, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x24f27e" - }, - "to":null, - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":9, - "data":"0x12345678", - "r":"0x06e79a060942823dc5b328a5b059b58cf42372c03617122139deb5b7844c043d", - "s":"0xfabd07fab3f36816397917ae8c048a4675d34d4ca3f7b06ca6595796a159d359", - "v":62710, - "creates":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x709bb2a24ac6120a12bf56e806cfcf3ceab71a41408b0685892800eebc4e3a45", - "parentHash":"0x65f3831f69d1e746f30d07a3def1eefdcc6650ee0714cbac795c2be3ce9430a2", - "number":11, - "timestamp":1603404112, - "nonce":"0x0000000000000042", - "difficulty":131712, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x2b5cd67036954f3c4cce09951c076adb3d0517750167e712562abba7910bd536", - "blockHash":"0x709bb2a24ac6120a12bf56e806cfcf3ceab71a41408b0685892800eebc4e3a45", - "blockNumber":11, - "transactionIndex":0, - "confirmations":6, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x0f4240" - }, - "to":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":10, - "data":"0x6fee07e00000000000000000000000000101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000201111111111111111111111111111111111111111111111111111111111111111", - "r":"0x7538f2153c482a762f133f1438b30c8874887f6da52f04adeba5cc65632ee661", - "s":"0x3dc3a219d164b159ad61f874ccb5c75766cb1d73954196eaba142d890b299d0e", - "v":62710, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x13e683738bac942ae739e45b0a0e451b20d7e986d9463a2dac0acf2015e8d09b", - "parentHash":"0x709bb2a24ac6120a12bf56e806cfcf3ceab71a41408b0685892800eebc4e3a45", - "number":12, - "timestamp":1603404113, - "nonce":"0x0000000000000042", - "difficulty":131776, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x339282191d55c5b9fc53d68f199c53ea9b946c9975ed34f15312acd8a70054f7", - "blockHash":"0x13e683738bac942ae739e45b0a0e451b20d7e986d9463a2dac0acf2015e8d09b", - "blockNumber":12, - "transactionIndex":0, - "confirmations":5, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x0f4240" - }, - "to":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":11, - "data":"0x6fee07e00000000000000000000000000101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000202222222222222222222222222222222222222222222222222222222222222222", - "r":"0x4ab1b83146fbfa4f0cce0110149c2c52e57971ce7cbe5b97a3fd3086bf9f0935", - "s":"0x11dac6b6c1e1d66a89d833ddd230120e6ecdedf49ae9fb38496f4385cb80057d", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x382c468636dafe28d7b3aad0f0521c2e7b9395fc0146b16502d85fa2a49ffe7b", - "parentHash":"0x13e683738bac942ae739e45b0a0e451b20d7e986d9463a2dac0acf2015e8d09b", - "number":13, - "timestamp":1603404114, - "nonce":"0x0000000000000042", - "difficulty":131840, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x8c260f877daaaaeba12b41da6763ce2a641a55ec2e545c4dcbc211b340480e93", - "blockHash":"0x382c468636dafe28d7b3aad0f0521c2e7b9395fc0146b16502d85fa2a49ffe7b", - "blockNumber":13, - "transactionIndex":0, - "confirmations":4, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x0f4240" - }, - "to":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":12, - "data":"0x6fee07e00000000000000000000000000101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000203333333333333333333333333333333333333333333333333333333333333333", - "r":"0x52f5316fc04aafc95110ac6be222ed656cd0a4ace50fac3e09384408c8b7e32a", - "s":"0x03de7779650526057629e842c45017cfd2dc19137d309cd99f244c0ce9b13186", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x5e5f592a3c96a45bc7fceea8681d066af84709dc155d305fe4e3d68f0bb7bd63", - "parentHash":"0x382c468636dafe28d7b3aad0f0521c2e7b9395fc0146b16502d85fa2a49ffe7b", - "number":14, - "timestamp":1603404115, - "nonce":"0x0000000000000042", - "difficulty":131904, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x2fbd6a3a19c6e5778762619ecfd849b4c3beb35bce0c99b1f357077f3380fa9e", - "blockHash":"0x5e5f592a3c96a45bc7fceea8681d066af84709dc155d305fe4e3d68f0bb7bd63", - "blockNumber":14, - "transactionIndex":0, - "confirmations":3, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x0f4240" - }, - "to":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":13, - "data":"0x6fee07e00000000000000000000000000101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000204444444444444444444444444444444444444444444444444444444444444444", - "r":"0x546c5a59b1753dd9b9f1f7ff0ae10f6f7fe07bfadf9882e140a021b0ca1a8ab4", - "s":"0x8b6c62b492ea8cf8e7dc8e8236ce7283a24e18370ce7950bda5f450fb7993547", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - }, - { - "hash":"0x13be1ecbdbaae00332acaa341ea3168781b112e7aff368a8bab060fa102085f4", - "parentHash":"0x5e5f592a3c96a45bc7fceea8681d066af84709dc155d305fe4e3d68f0bb7bd63", - "number":15, - "timestamp":1603404116, - "nonce":"0x0000000000000042", - "difficulty":131968, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x02625a00" - }, - "gasUsed":{ - "type":"BigNumber", - "hex":"0x00" - }, - "miner":"0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E", - "extraData":"0x", - "transactions":[ - { - "hash":"0x3a60f459be600341f831b6e9b6b75a242cd31d1e4ae6b0bbd763a6b56054ef7b", - "blockHash":"0x13be1ecbdbaae00332acaa341ea3168781b112e7aff368a8bab060fa102085f4", - "blockNumber":15, - "transactionIndex":0, - "confirmations":2, - "from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", - "gasPrice":{ - "type":"BigNumber", - "hex":"0x01dcd65000" - }, - "gasLimit":{ - "type":"BigNumber", - "hex":"0x0f4240" - }, - "to":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", - "value":{ - "type":"BigNumber", - "hex":"0x00" - }, - "nonce":14, - "data":"0x6fee07e00000000000000000000000000101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000c350000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000205555555555555555555555555555555555555555555555555555555555555555", - "r":"0x3b214ae35181aaf5542f970325ef36ca881db2fc1b145524534a4fb6885b05d7", - "s":"0xdf4fd847db5d5a246f4cedd2dee14e15e70ff469a7d88cdc86efa7c6d61d7cad", - "v":62709, - "creates":null, - "l1BlockNumber":"1", - "l1TxOrigin":"0x3333333333333333333333333333333333333333", - "rawTransaction":"0x420420", - "signatureHashType":"0", - "queueOrigin":"sequencer", - "chainId":31337 - } - ] - } - ] -`) diff --git a/packages/batch-submitter/test/helpers/constants.ts b/packages/batch-submitter/test/helpers/constants.ts deleted file mode 100644 index a197c8f50c461..0000000000000 --- a/packages/batch-submitter/test/helpers/constants.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* External Imports */ -import { defaultAccounts } from 'ethereum-waffle' - -export const FORCE_INCLUSION_PERIOD_SECONDS = 600 -export const DEFAULT_ACCOUNTS = defaultAccounts -export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => { - return { - balance: account.balance, - privateKey: account.secretKey, - } -}) - -export const OVM_TX_GAS_LIMIT = 10_000_000 -export const RUN_OVM_TEST_GAS = 20_000_000 diff --git a/packages/batch-submitter/test/helpers/dummy/bytecode.ts b/packages/batch-submitter/test/helpers/dummy/bytecode.ts deleted file mode 100644 index 7388c78ad87cd..0000000000000 --- a/packages/batch-submitter/test/helpers/dummy/bytecode.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* External Imports */ -import { keccak256 } from 'ethers/lib/utils' - -export const DUMMY_BYTECODE = '0x123412341234' -export const DUMMY_BYTECODE_BYTELEN = 6 -export const DUMMY_BYTECODE_HASH = keccak256(DUMMY_BYTECODE) diff --git a/packages/batch-submitter/test/helpers/dummy/bytes32.ts b/packages/batch-submitter/test/helpers/dummy/bytes32.ts deleted file mode 100644 index 070ac1a0f2fd7..0000000000000 --- a/packages/batch-submitter/test/helpers/dummy/bytes32.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* External Imports */ -import { ethers } from 'ethers' - -export const DUMMY_BYTES32: string[] = Array.from( - { - length: 10, - }, - (_, i) => { - return ethers.utils.keccak256(`0x0${i}`) - } -) diff --git a/packages/batch-submitter/test/helpers/dummy/index.ts b/packages/batch-submitter/test/helpers/dummy/index.ts deleted file mode 100644 index f0e9687669436..0000000000000 --- a/packages/batch-submitter/test/helpers/dummy/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './bytes32' -export * from './bytecode' diff --git a/packages/batch-submitter/test/helpers/index.ts b/packages/batch-submitter/test/helpers/index.ts deleted file mode 100644 index 0473fe33e25ef..0000000000000 --- a/packages/batch-submitter/test/helpers/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './dummy' -export * from './constants' -export * from './resolver' diff --git a/packages/batch-submitter/test/helpers/resolver/address-manager.ts b/packages/batch-submitter/test/helpers/resolver/address-manager.ts deleted file mode 100644 index 41716acae9fc5..0000000000000 --- a/packages/batch-submitter/test/helpers/resolver/address-manager.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* External Imports */ -import { ethers } from 'hardhat' -import { Contract } from 'ethers' -import { getContractFactory as ctFactory } from 'old-contracts' - -export const getContractFactory = async (contract: string) => - ctFactory(contract, (await ethers.getSigners())[0]) - -export const setProxyTarget = async ( - AddressManager: Contract, - name: string, - target: Contract -): Promise => { - const SimpleProxy: Contract = await ( - await getContractFactory('Helper_SimpleProxy') - ).deploy() - - await SimpleProxy.setTarget(target.address) - await AddressManager.setAddress(name, SimpleProxy.address) -} - -export const makeAddressManager = async (): Promise => { - return (await getContractFactory('Lib_AddressManager')).deploy() -} diff --git a/packages/batch-submitter/test/helpers/resolver/index.ts b/packages/batch-submitter/test/helpers/resolver/index.ts deleted file mode 100644 index 52516689c177d..0000000000000 --- a/packages/batch-submitter/test/helpers/resolver/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './address-manager' diff --git a/packages/batch-submitter/test/setup.ts b/packages/batch-submitter/test/setup.ts deleted file mode 100644 index 290684bb3c4d5..0000000000000 --- a/packages/batch-submitter/test/setup.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* External Imports */ -import chai = require('chai') -import sinonChai from 'sinon-chai' -import Mocha from 'mocha' - -const should = chai.should() -const expect = chai.expect -chai.use(sinonChai) - -export { should, expect, chai, Mocha } diff --git a/packages/batch-submitter/test/utils/tx-submission.spec.ts b/packages/batch-submitter/test/utils/tx-submission.spec.ts deleted file mode 100644 index 756b7afe67b78..0000000000000 --- a/packages/batch-submitter/test/utils/tx-submission.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { ethers, BigNumber, Signer } from 'ethers' -import { - TransactionReceipt, - TransactionResponse, -} from '@ethersproject/abstract-provider' - -import { expect } from '../setup' -import { submitTransactionWithYNATM } from '../../src/utils/tx-submission' -import { ResubmissionConfig } from '../../src' - -const nullFunction = () => undefined -const nullHooks = { - beforeSendTransaction: nullFunction, - onTransactionResponse: nullFunction, -} - -describe('submitTransactionWithYNATM', async () => { - it('calls sendTransaction, waitForTransaction, and hooks with correct inputs', async () => { - const called = { - sendTransaction: false, - waitForTransaction: false, - beforeSendTransaction: false, - onTransactionResponse: false, - } - const dummyHash = 'dummy hash' - const numConfirmations = 3 - const tx = { - data: 'we here though', - } as ethers.PopulatedTransaction - const sendTransaction = async ( - _tx: ethers.PopulatedTransaction - ): Promise => { - called.sendTransaction = true - expect(_tx.data).to.equal(tx.data) - return { - hash: dummyHash, - } as TransactionResponse - } - const waitForTransaction = async ( - hash: string, - _numConfirmations: number - ): Promise => { - called.waitForTransaction = true - expect(hash).to.equal(dummyHash) - expect(_numConfirmations).to.equal(numConfirmations) - return { - to: '', - from: '', - status: 1, - } as TransactionReceipt - } - const signer = { - getGasPrice: async () => ethers.BigNumber.from(0), - sendTransaction, - provider: { - waitForTransaction, - }, - } as Signer - const hooks = { - beforeSendTransaction: (submittingTx: ethers.PopulatedTransaction) => { - called.beforeSendTransaction = true - expect(submittingTx.data).to.equal(tx.data) - }, - onTransactionResponse: (txResponse: TransactionResponse) => { - called.onTransactionResponse = true - expect(txResponse.hash).to.equal(dummyHash) - }, - } - const config: ResubmissionConfig = { - resubmissionTimeout: 1000, - minGasPriceInGwei: 0, - maxGasPriceInGwei: 0, - gasRetryIncrement: 1, - } - await submitTransactionWithYNATM( - tx, - signer, - config, - numConfirmations, - hooks - ) - expect(called.sendTransaction).to.be.true - expect(called.waitForTransaction).to.be.true - expect(called.beforeSendTransaction).to.be.true - expect(called.onTransactionResponse).to.be.true - }) - - it('repeatedly increases the gas limit of the transaction when wait takes too long', async () => { - // Make transactions take longer to be included - // than our resubmission timeout - const resubmissionTimeout = 100 - const txReceiptDelay = resubmissionTimeout * 3 - let lastGasPrice = BigNumber.from(0) - // Create a transaction which has a gas price that we will watch increment - const tx = { - gasPrice: lastGasPrice.add(1), - data: 'hello world!', - } as ethers.PopulatedTransaction - const sendTransaction = async ( - _tx: ethers.PopulatedTransaction - ): Promise => { - // Ensure the gas price is always increasing - expect(_tx.gasPrice > lastGasPrice).to.be.true - lastGasPrice = _tx.gasPrice - return { - hash: 'dummy hash', - } as TransactionResponse - } - const waitForTransaction = async (): Promise => { - await new Promise((r) => setTimeout(r, txReceiptDelay)) - return {} as TransactionReceipt - } - const signer = { - getGasPrice: async () => ethers.BigNumber.from(0), - sendTransaction, - provider: { - waitForTransaction: waitForTransaction as any, - }, - } as Signer - const config: ResubmissionConfig = { - resubmissionTimeout, - minGasPriceInGwei: 0, - maxGasPriceInGwei: 1000, - gasRetryIncrement: 1, - } - await submitTransactionWithYNATM(tx, signer, config, 0, nullHooks) - }) - - it('should immediately reject if a nonce error is encountered', async () => { - const tx = { - gasPrice: BigNumber.from(1), - data: 'hello world!', - } as ethers.PopulatedTransaction - - let txCount = 0 - const waitForTransaction = async (): Promise => { - return {} as TransactionReceipt - } - const sendTransaction = async () => { - txCount++ - throw new Error('Transaction nonce is too low.') - } - const signer = { - getGasPrice: async () => BigNumber.from(1), - sendTransaction: sendTransaction as any, - provider: { - waitForTransaction: waitForTransaction as any, - }, - } as Signer - - const config: ResubmissionConfig = { - resubmissionTimeout: 100, - minGasPriceInGwei: 0, - maxGasPriceInGwei: 1000, - gasRetryIncrement: 1, - } - try { - await submitTransactionWithYNATM(tx, signer, config, 0, nullHooks) - } catch (e) { - expect(txCount).to.equal(1) - return - } - expect.fail('Expected an error.') - }) -}) diff --git a/packages/batch-submitter/tsconfig.build.json b/packages/batch-submitter/tsconfig.build.json deleted file mode 100644 index dcd3fe90606d7..0000000000000 --- a/packages/batch-submitter/tsconfig.build.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - - "compilerOptions": { - "outDir": "./dist" - }, - - "include": [ - "src/**/*" - ] -} diff --git a/packages/batch-submitter/tsconfig.json b/packages/batch-submitter/tsconfig.json deleted file mode 100644 index 578447f2ea578..0000000000000 --- a/packages/batch-submitter/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "resolveJsonModule": true - } -} diff --git a/yarn.lock b/yarn.lock index ce81c8d2d276f..39181d7466042 100644 --- a/yarn.lock +++ b/yarn.lock @@ -514,28 +514,6 @@ "@eth-optimism/core-utils" "^0.5.1" bn.js "^5.2.0" -"@eth-optimism/solc@^0.6.12-alpha.1": - version "0.6.12-alpha.1" - resolved "https://registry.yarnpkg.com/@eth-optimism/solc/-/solc-0.6.12-alpha.1.tgz#041876f83b34c6afe2f19dfe9626568df6ed8590" - integrity sha512-Ky73mo+2iNJs/VTaT751nMeZ7hXns0TBAlffTOxIOsScjAZ/zi/KWsDUo3r89aV2JKXcYAU/bLidxF40MVJeUw== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - follow-redirects "^1.12.1" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -"@eth-optimism/ynatm@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@eth-optimism/ynatm/-/ynatm-0.2.2.tgz#b1f165c3149188f184b66329228746260ae18677" - integrity sha512-R/hIAFWEj2sjf3inNEGCffmGofqMFY/7PS/Hh4A/62Kg0wMM8rsyMyW8pXngMnD/EQAjR8WTtKDutq/L5vSMTQ== - dependencies: - bluebird "^3.7.2" - "@ethereum-waffle/chai@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.0.tgz#2477877410a96bf370edd64df905b04fb9aba9d5" @@ -689,7 +667,7 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abi@5.4.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0": +"@ethersproject/abi@5.4.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.4.0.tgz#a6d63bdb3672f738398846d4279fa6b6c9818242" integrity sha512-9gU2H+/yK1j2eVMdzm6xvHSnMxk8waIHQGYCZg5uvAyH0rsAzxkModzBSpbAkAuhKFEovC2S9hM4nPuLym8IZw== @@ -734,7 +712,7 @@ "@ethersproject/properties" "^5.4.0" "@ethersproject/strings" "^5.4.0" -"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.0.0", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.4.1": +"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== @@ -760,7 +738,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/web" "^5.5.0" -"@ethersproject/abstract-signer@5.4.1", "@ethersproject/abstract-signer@^5.0.0", "@ethersproject/abstract-signer@^5.4.0", "@ethersproject/abstract-signer@^5.4.1": +"@ethersproject/abstract-signer@5.4.1", "@ethersproject/abstract-signer@^5.4.0", "@ethersproject/abstract-signer@^5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== @@ -782,7 +760,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/properties" "^5.5.0" -"@ethersproject/address@5.4.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": +"@ethersproject/address@5.4.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== @@ -804,7 +782,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" -"@ethersproject/base64@5.4.0", "@ethersproject/base64@^5.0.0", "@ethersproject/base64@^5.4.0": +"@ethersproject/base64@5.4.0", "@ethersproject/base64@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== @@ -834,7 +812,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/properties" "^5.5.0" -"@ethersproject/bignumber@5.4.1", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": +"@ethersproject/bignumber@5.4.1", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": version "5.4.1" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.1.tgz#64399d3b9ae80aa83d483e550ba57ea062c1042d" integrity sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg== @@ -861,7 +839,7 @@ "@ethersproject/logger" "^5.4.0" bn.js "^4.11.9" -"@ethersproject/bytes@5.4.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": +"@ethersproject/bytes@5.4.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== @@ -875,7 +853,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/constants@5.4.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": +"@ethersproject/constants@5.4.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== @@ -889,7 +867,7 @@ dependencies: "@ethersproject/bignumber" "^5.5.0" -"@ethersproject/contracts@5.4.1", "@ethersproject/contracts@^5.0.0", "@ethersproject/contracts@^5.0.5", "@ethersproject/contracts@^5.4.1": +"@ethersproject/contracts@5.4.1", "@ethersproject/contracts@^5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.4.1.tgz#3eb4f35b7fe60a962a75804ada2746494df3e470" integrity sha512-m+z2ZgPy4pyR15Je//dUaymRUZq5MtDajF6GwFbGAVmKz/RF+DNIPwF0k5qEcL3wPGVqUjFg2/krlCRVTU4T5w== @@ -921,18 +899,6 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" -"@ethersproject/hardware-wallets@^5.0.8": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.4.0.tgz#bce275b395e26b6f50481095331157614490a473" - integrity sha512-Ea4ymm4etZoSWy93OcEGZkuVqyYdl/RjMlaXY6yQIYjsGi75sm4apbTiBA8DA9uajkv1FVakJZEBBTaVGgnBLA== - dependencies: - "@ledgerhq/hw-app-eth" "5.27.2" - "@ledgerhq/hw-transport" "5.26.0" - "@ledgerhq/hw-transport-u2f" "5.26.0" - ethers "^5.4.0" - optionalDependencies: - "@ledgerhq/hw-transport-node-hid" "5.26.0" - "@ethersproject/hardware-wallets@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.5.0.tgz#b4a3bc99a843c3b78b133cdf94485a567ba17b8d" @@ -945,7 +911,7 @@ optionalDependencies: "@ledgerhq/hw-transport-node-hid" "5.26.0" -"@ethersproject/hash@5.4.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.0", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.4.0": +"@ethersproject/hash@5.4.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== @@ -973,7 +939,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/hdnode@5.4.0", "@ethersproject/hdnode@^5.0.0", "@ethersproject/hdnode@^5.4.0": +"@ethersproject/hdnode@5.4.0", "@ethersproject/hdnode@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.4.0.tgz#4bc9999b9a12eb5ce80c5faa83114a57e4107cac" integrity sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q== @@ -1009,7 +975,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" -"@ethersproject/json-wallets@5.4.0", "@ethersproject/json-wallets@^5.0.0", "@ethersproject/json-wallets@^5.4.0": +"@ethersproject/json-wallets@5.4.0", "@ethersproject/json-wallets@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.4.0.tgz#2583341cfe313fc9856642e8ace3080154145e95" integrity sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ== @@ -1047,7 +1013,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.4.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": +"@ethersproject/keccak256@5.4.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== @@ -1063,7 +1029,7 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.4.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": +"@ethersproject/logger@5.4.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.0.tgz#f39adadf62ad610c420bcd156fd41270e91b3ca9" integrity sha512-xYdWGGQ9P2cxBayt64d8LC8aPFJk6yWCawQi/4eJ4+oJdMMjEBMrIcIMZ9AxhwpPVmnBPrsB10PcXGmGAqgUEQ== @@ -1073,7 +1039,7 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== -"@ethersproject/networks@5.4.2", "@ethersproject/networks@^5.0.0", "@ethersproject/networks@^5.4.0": +"@ethersproject/networks@5.4.2", "@ethersproject/networks@^5.4.0": version "5.4.2" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== @@ -1087,7 +1053,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/pbkdf2@5.4.0", "@ethersproject/pbkdf2@^5.0.0", "@ethersproject/pbkdf2@^5.4.0": +"@ethersproject/pbkdf2@5.4.0", "@ethersproject/pbkdf2@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.4.0.tgz#ed88782a67fda1594c22d60d0ca911a9d669641c" integrity sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g== @@ -1103,7 +1069,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/sha2" "^5.5.0" -"@ethersproject/properties@5.4.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": +"@ethersproject/properties@5.4.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.0.tgz#38ba20539b44dcc5d5f80c45ad902017dcdbefe7" integrity sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A== @@ -1117,7 +1083,7 @@ dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/providers@5.4.4", "@ethersproject/providers@^5.0.0": +"@ethersproject/providers@5.4.4": version "5.4.4" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.4.4.tgz#6729120317942fc0ab0ecdb35e944ec6bbedb795" integrity sha512-mQevyXj2X2D3l8p/JGDYFZbODhZjW6On15DnCK4Xc9y6b+P0vqorQC/j46omWSm4cyo7BQ/rgfhXNYmvAfyZoQ== @@ -1192,7 +1158,7 @@ bech32 "1.1.4" ws "7.4.6" -"@ethersproject/random@5.4.0", "@ethersproject/random@^5.0.0", "@ethersproject/random@^5.4.0": +"@ethersproject/random@5.4.0", "@ethersproject/random@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.4.0.tgz#9cdde60e160d024be39cc16f8de3b9ce39191e16" integrity sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw== @@ -1216,7 +1182,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.0.0", "@ethersproject/rlp@^5.4.0": +"@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== @@ -1232,7 +1198,7 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/sha2@5.4.0", "@ethersproject/sha2@^5.0.0", "@ethersproject/sha2@^5.4.0": +"@ethersproject/sha2@5.4.0", "@ethersproject/sha2@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.4.0.tgz#c9a8db1037014cbc4e9482bd662f86c090440371" integrity sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg== @@ -1250,7 +1216,7 @@ "@ethersproject/logger" "^5.5.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.4.0", "@ethersproject/signing-key@^5.0.0", "@ethersproject/signing-key@^5.4.0": +"@ethersproject/signing-key@5.4.0", "@ethersproject/signing-key@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== @@ -1274,7 +1240,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.4.0", "@ethersproject/solidity@^5.0.0", "@ethersproject/solidity@^5.0.9", "@ethersproject/solidity@^5.4.0": +"@ethersproject/solidity@5.4.0", "@ethersproject/solidity@^5.0.9", "@ethersproject/solidity@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.4.0.tgz#1305e058ea02dc4891df18b33232b11a14ece9ec" integrity sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ== @@ -1297,7 +1263,7 @@ "@ethersproject/sha2" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/strings@5.4.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": +"@ethersproject/strings@5.4.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== @@ -1315,7 +1281,7 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/transactions@5.4.0", "@ethersproject/transactions@^5.0.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0": +"@ethersproject/transactions@5.4.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== @@ -1345,7 +1311,7 @@ "@ethersproject/rlp" "^5.5.0" "@ethersproject/signing-key" "^5.5.0" -"@ethersproject/units@5.4.0", "@ethersproject/units@^5.0.0": +"@ethersproject/units@5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.4.0.tgz#d57477a4498b14b88b10396062c8cbbaf20c79fe" integrity sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg== @@ -1363,7 +1329,7 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/wallet@5.4.0", "@ethersproject/wallet@^5.0.0", "@ethersproject/wallet@^5.4.0": +"@ethersproject/wallet@5.4.0", "@ethersproject/wallet@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.4.0.tgz#fa5b59830b42e9be56eadd45a16a2e0933ad9353" integrity sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ== @@ -1405,7 +1371,7 @@ "@ethersproject/transactions" "^5.5.0" "@ethersproject/wordlists" "^5.5.0" -"@ethersproject/web@5.4.0", "@ethersproject/web@^5.0.0", "@ethersproject/web@^5.4.0": +"@ethersproject/web@5.4.0", "@ethersproject/web@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== @@ -1427,7 +1393,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.0.0", "@ethersproject/wordlists@^5.4.0": +"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.4.0.tgz#f34205ec3bbc9e2c49cadaee774cf0b07e7573d7" integrity sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA== @@ -2523,11 +2489,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6" integrity sha512-AybF1cesONZStg5kWf6ao9OlqTZuPqddvprc0ky7lrUVOjXeKpmQ2Y9FK+6ygxasb+4aic4O5pneFBfwVsRRRg== -"@openzeppelin/contracts@^3.3.0": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2.tgz#d81f786fda2871d1eb8a8c5a73e455753ba53527" - integrity sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA== - "@openzeppelin/contracts@^4.3.2": version "4.3.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.3.tgz#ff6ee919fc2a1abaf72b22814bfb72ed129ec137" @@ -2723,20 +2684,13 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": +"@sinonjs/commons@^1.7.0": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" - integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== - dependencies: - "@sinonjs/commons" "^1.7.0" - "@sinonjs/fake-timers@^7.1.0": version "7.1.2" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" @@ -2744,20 +2698,6 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@sinonjs/samsam@^5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.3.1.tgz#375a45fe6ed4e92fca2fb920e007c48232a6507f" - integrity sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg== - dependencies: - "@sinonjs/commons" "^1.6.0" - lodash.get "^4.4.2" - type-detect "^4.0.8" - -"@sinonjs/text-encoding@^0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" - integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== - "@solidity-parser/parser@^0.11.0": version "0.11.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.11.1.tgz#fa840af64840c930f24a9c82c08d4a092a068add" @@ -2864,11 +2804,6 @@ resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.2.tgz#ee81917fe38f770e29eec8139b6f16ee4a8b0a5f" integrity sha512-+jA1XXF3jsz+Z7FcuiNqgK53hTa/luglT2TyTpKPqoYbxVY+mCPF22Rm+q3KPBrMHJwNXFrTViHszBOfU4vftQ== -"@types/bluebird@^3.5.34": - version "3.5.36" - resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652" - integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q== - "@types/bn.js@*", "@types/bn.js@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" @@ -3175,7 +3110,7 @@ "@types/mime" "^1" "@types/node" "*" -"@types/sinon-chai@^3.2.3", "@types/sinon-chai@^3.2.5": +"@types/sinon-chai@^3.2.3": version "3.2.5" resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.5.tgz#df21ae57b10757da0b26f512145c065f2ad45c48" integrity sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ== @@ -3190,18 +3125,6 @@ dependencies: "@sinonjs/fake-timers" "^7.1.0" -"@types/sinon@^9.0.10": - version "9.0.11" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.11.tgz#7af202dda5253a847b511c929d8b6dda170562eb" - integrity sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz#79df6f358ae8f79e628fe35a63608a0ea8e7cf08" - integrity sha512-E1dU4fzC9wN2QK2Cr1MLCfyHM8BoNnRFvuf45LYMPNDA+WqbNzC45S4UzPxvp1fFJ1rvSGU0bPvdd35VLmXG8g== - "@types/tz-offset@*": version "0.0.0" resolved "https://registry.yarnpkg.com/@types/tz-offset/-/tz-offset-0.0.0.tgz#d58f1cebd794148d245420f8f0660305d320e565" @@ -4594,7 +4517,7 @@ blakejs@^1.1.0: resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== -bluebird@^3.5.0, bluebird@^3.5.2, bluebird@^3.5.3, bluebird@^3.5.5, bluebird@^3.7.2: +bluebird@^3.5.0, bluebird@^3.5.2, bluebird@^3.5.3, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -6165,7 +6088,7 @@ diff@5.0.0, diff@^5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -diff@^4.0.1, diff@^4.0.2: +diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== @@ -7238,41 +7161,6 @@ ethereumjs-wallet@0.6.5: utf8 "^3.0.0" uuid "^3.3.2" -ethers@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.0.0.tgz#76558a3020766f310a49f4e1a4c6c1e331761abd" - integrity sha512-uOSACd2E8dg8XuiOewpL42uFH7SvrkA5k0oGkHoqSJl2lflrMPV+7ciWzyuPBjyHnOFvAPPJUpsXrwpFKaLFww== - dependencies: - "@ethersproject/abi" "^5.0.0" - "@ethersproject/abstract-provider" "^5.0.0" - "@ethersproject/abstract-signer" "^5.0.0" - "@ethersproject/address" "^5.0.0" - "@ethersproject/base64" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/contracts" "^5.0.0" - "@ethersproject/hash" "^5.0.0" - "@ethersproject/hdnode" "^5.0.0" - "@ethersproject/json-wallets" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/networks" "^5.0.0" - "@ethersproject/pbkdf2" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/providers" "^5.0.0" - "@ethersproject/random" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - "@ethersproject/sha2" "^5.0.0" - "@ethersproject/signing-key" "^5.0.0" - "@ethersproject/solidity" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - "@ethersproject/transactions" "^5.0.0" - "@ethersproject/units" "^5.0.0" - "@ethersproject/wallet" "^5.0.0" - "@ethersproject/web" "^5.0.0" - "@ethersproject/wordlists" "^5.0.0" - ethers@^4.0.32, ethers@^4.0.40: version "4.0.49" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" @@ -7288,7 +7176,7 @@ ethers@^4.0.32, ethers@^4.0.40: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.0, ethers@^5.4.5: +ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5: version "5.4.5" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.4.5.tgz#cec133b9f5b514dc55e2561ee7aa7218c33affd7" integrity sha512-PPZ6flOAj230sXEWf/r/It6ZZ5c7EOVWx+PU87Glkbg79OtT7pLE1WgL4MRdwx6iF7HzSOvUUI+8cAmcdzo12w== @@ -8069,7 +7957,7 @@ ganache-cli@^6.12.2: source-map-support "0.5.12" yargs "13.2.4" -ganache-core@^2.12.1, ganache-core@^2.13.2: +ganache-core@^2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== @@ -9865,11 +9753,6 @@ jsprim@^1.2.2: array-includes "^3.1.2" object.assign "^4.1.2" -just-extend@^4.0.2: - version "4.2.1" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" - integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== - keccak@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" @@ -10377,11 +10260,6 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -11363,17 +11241,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nise@^4.0.4: - version "4.1.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-4.1.0.tgz#8fb75a26e90b99202fa1e63f448f58efbcdedaf6" - integrity sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA== - dependencies: - "@sinonjs/commons" "^1.7.0" - "@sinonjs/fake-timers" "^6.0.0" - "@sinonjs/text-encoding" "^0.7.1" - just-extend "^4.0.2" - path-to-regexp "^1.7.0" - node-abi@^2.18.0, node-abi@^2.21.0, node-abi@^2.7.0: version "2.30.0" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.0.tgz#8be53bf3e7945a34eea10e0fc9a5982776cf550b" @@ -11877,18 +11744,6 @@ oboe@2.1.5: dependencies: http-https "^1.0.0" -"old-contracts@npm:@eth-optimism/contracts@^0.0.2-alpha.7": - version "0.0.2-alpha.15" - resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.0.2-alpha.15.tgz#d602bdb6f1186d111ce9f7c282fc80e023086892" - integrity sha512-upJfYHDWQY7nM0AYT9MKQiuOus2uMUhvqS962qiBq3Ly/9GUq5mS0UALynsrZBGbzT6pflOMKFFEv7jQEORGmA== - dependencies: - "@eth-optimism/solc" "^0.6.12-alpha.1" - "@ethersproject/contracts" "^5.0.5" - "@ethersproject/hardware-wallets" "^5.0.8" - "@openzeppelin/contracts" "^3.3.0" - ethers "5.0.0" - ganache-core "^2.12.1" - on-finished@^2.3.0, on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -12349,13 +12204,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -13889,23 +13737,6 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" -sinon-chai@^3.5.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783" - integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g== - -sinon@^9.2.4: - version "9.2.4" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.2.4.tgz#e55af4d3b174a4443a8762fa8421c2976683752b" - integrity sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg== - dependencies: - "@sinonjs/commons" "^1.8.1" - "@sinonjs/fake-timers" "^6.0.1" - "@sinonjs/samsam" "^5.3.1" - diff "^4.0.2" - nise "^4.0.4" - supports-color "^7.1.0" - slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -15203,7 +15034,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==