Commit 75055b51 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #2359 from ethereum-optimism/develop

Develop -> Master
parents 1c858502 0645cd7c
---
'@eth-optimism/replica-healthcheck': patch
---
Fixes a bug in the replica-healthcheck docker file
---
'@eth-optimism/teleportr': patch
---
Add metrics for balances
---
'@eth-optimism/l2geth-exporter': patch
---
Bump to go-ethereum v1.10.16
---
'@eth-optimism/common-ts': patch
---
Properly exposes metrics as part of a metrics server at port 7300
---
'@eth-optimism/integration-tests': patch
---
Add integration test for healthcheck server
---
'@eth-optimism/replica-healthcheck': patch
---
Add checks and metrics for dead networks
---
'@eth-optimism/gas-oracle': patch
---
Allow configurable base fee update poll time with `GAS_PRICE_ORACLE_L1_BASE_FEE_EPOCH_LENGTH_SECONDS`
...@@ -7,32 +7,13 @@ slack-nightly-build-fail-post-step: &slack-nightly-build-fail-post-step ...@@ -7,32 +7,13 @@ slack-nightly-build-fail-post-step: &slack-nightly-build-fail-post-step
- slack/notify: - slack/notify:
channel: $SLACK_DEFAULT_CHANNEL channel: $SLACK_DEFAULT_CHANNEL
event: fail event: fail
custom: | template: basic_fail-1
{
"text": "", executors:
"blocks": [ go-builder:
{ docker:
"type": "section", - image: ethereumoptimism/go-builder:latest
"text": {
"type": "mrkdwn",
"text": "🔴 Nightly build failed!"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Job"
},
"url": "${CIRCLE_BUILD_URL}"
}
]
}
]
}
commands: commands:
build-dockerfile: build-dockerfile:
parameters: parameters:
...@@ -56,6 +37,27 @@ commands: ...@@ -56,6 +37,27 @@ commands:
echo -n "$STACKMAN_REPO_AUTH" | docker login -u _json_key --password-stdin https://us-east4-docker.pkg.dev echo -n "$STACKMAN_REPO_AUTH" | docker login -u _json_key --password-stdin https://us-east4-docker.pkg.dev
docker build -t "$STACKMAN_REPO/<<parameters.image-name>>:nightly" -f <<parameters.dockerfile>> <<#parameters.target>>--target <<parameters.target>><</parameters.target>> . docker build -t "$STACKMAN_REPO/<<parameters.image-name>>:nightly" -f <<parameters.dockerfile>> <<#parameters.target>>--target <<parameters.target>><</parameters.target>> .
docker push "$STACKMAN_REPO/<<parameters.image-name>>:nightly" docker push "$STACKMAN_REPO/<<parameters.image-name>>:nightly"
go-lint-test:
parameters:
working_directory:
description: Working directory
type: string
steps:
- checkout
- run:
name: Lint
command: golangci-lint run -E goimports -E sqlclosecheck -E bodyclose -E asciicheck ./...
working_directory: <<parameters.working_directory>>
- run:
name: Test
command: |
mkdir -p /test-results
gotestsum --junitfile /test-results/tests.xml
working_directory: <<parameters.working_directory>>
- store_test_results:
path: /test-results
jobs: jobs:
build-dtl: build-dtl:
docker: docker:
...@@ -154,6 +156,7 @@ jobs: ...@@ -154,6 +156,7 @@ jobs:
--env L2_GAS_PRICE=onchain \ --env L2_GAS_PRICE=onchain \
--env RUN_DEBUG_TRACE_TESTS=false \ --env RUN_DEBUG_TRACE_TESTS=false \
--env RUN_REPLICA_TESTS=false \ --env RUN_REPLICA_TESTS=false \
--env RUN_HEALTHCHECK_TESTS=false \
--env RUN_STRESS_TESTS=false \ --env RUN_STRESS_TESTS=false \
--env OVMCONTEXT_SPEC_NUM_TXS=1 \ --env OVMCONTEXT_SPEC_NUM_TXS=1 \
--env DTL_ENQUEUE_CONFIRMATIONS=12 \ --env DTL_ENQUEUE_CONFIRMATIONS=12 \
...@@ -168,8 +171,294 @@ jobs: ...@@ -168,8 +171,294 @@ jobs:
command: | command: |
echo "Dummy job." echo "Dummy job."
go-lint-test:
parameters:
working_directory:
description: Working directory
type: string
docker:
- image: ethereumoptimism/go-builder:latest
- image: cimg/postgres:14.1
steps:
- go-lint-test:
working_directory: <<parameters.working_directory>>
go-lint-test-build:
parameters:
binary_name:
description: Binary name to build
type: string
working_directory:
description: Working directory
type: string
docker:
- image: ethereumoptimism/go-builder:latest
- image: cimg/postgres:14.1
steps:
- go-lint-test:
working_directory: <<parameters.working_directory>>
- run:
name: Build
command: make <<parameters.binary_name>>
working_directory: <<parameters.working_directory>>
yarn-monorepo:
docker:
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v1-source-{{ .Branch }}-{{ .Revision }}
- v1-source-{{ .Branch }}
- checkout
- save_cache:
key: v1-source-{{ .Branch }}-{{ .Revision }}
paths:
- ".git"
- restore_cache:
keys:
- v1-yarn-install-{{ checksum "yarn.lock" }}
- v1-yarn-install
- run:
name: Install dependencies
command: yarn --frozen-lockfile
- save_cache:
key: v1-yarn-install-{{ checksum "yarn.lock" }}
paths:
- node_modules
- packages/common-ts/node_modules
- packages/contracts/node_modules
- packages/core-utils/node_modules
- packages/data-transport-layer/node_modules
- packages/message-relayer/node_modules
- packages/replica-healthcheck/node_modules
- packages/sdk/node_modules
- integration-tests/node_modules
- run:
name: Build monorepo
command: yarn build
- save_cache:
key: v1-yarn-build-{{ .Revision }}
paths:
- "."
contracts-slither:
docker:
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v1-yarn-build-{{ .Revision }}
- checkout
- run:
name: Run Slither
command: yarn test:slither
working_directory: packages/contracts
contracts-tests:
docker:
- image: ethereumoptimism/js-builder:latest
resource_class: xlarge
steps:
- restore_cache:
keys:
- v1-yarn-build-{{ .Revision }}
- checkout
- run:
name: Lint
command: yarn lint:check
working_directory: packages/contracts
- run:
name: Slither
command: yarn test:slither
working_directory: packages/contracts
- run:
name: Test
command: yarn test:coverage
working_directory: packages/contracts
dtl-tests:
docker:
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v1-yarn-build-{{ .Revision }}
- checkout
- run:
name: Test
command: yarn test:coverage
working_directory: packages/data-transport-layer
geth-tests:
docker:
- image: ethereumoptimism/go-builder:latest
steps:
- checkout
- run:
name: Test
command: make test
working_directory: l2geth
depcheck:
docker:
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v1-yarn-build-{{ .Revision }}
- checkout
# Note: The below needs to be manually configured whenever we
# add a new package to CI.
- run:
name: Check contracts
command: npx depcheck
working_directory: packages/contracts
- run:
name: Check core-utils
command: npx depcheck
working_directory: packages/core-utils
- run:
name: Check data-transport-layer
command: npx depcheck
working_directory: packages/data-transport-layer
- run:
name: Check sdk
command: npx depcheck
working_directory: packages/sdk
- run:
name: Check integration-tests
command: npx depcheck
working_directory: integration-tests
bss-core-tests:
docker:
- image: ethereumoptimism/go-builder:latest
steps:
- checkout
- run:
name: Lint
command: golangci-lint run -E goimports -E sqlclosecheck -E bodyclose -E asciicheck ./...
working_directory: go/bss-core
- run:
name: Test
command: |
mkdir -p /test-results
gotestsum --junitfile /test-results/tests.xml
working_directory: go/bss-core
- store_test_results:
path: /test-results
integration-tests:
machine:
image: ubuntu-2004:202111-02
docker_layer_caching: true
environment:
DOCKER_BUILDKIT: 1
parallelism: 3
steps:
- checkout
- run:
name: Bring up the stack
command: |
docker-compose build --progress=plain
docker-compose up -d --scale replica-healthcheck=1
working_directory: ops
- run:
name: Wait for sequencer
command: bash scripts/wait-for-sequencer.sh
working_directory: ops
- run:
name: Run integration tests
command: |
circleci tests glob "../integration-tests/test/*.spec.ts" | circleci tests split | tee splits.txt
docker-compose run integration_tests $(cat splits.txt)
working_directory: ops
js-lint-test:
parameters:
package_name:
description: Package name
type: string
docker:
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v1-yarn-build-{{ .Revision }}
- checkout
- run:
name: Lint
command: yarn lint:check
working_directory: packages/<<parameters.package_name>>
- run:
name: Test
command: yarn test:coverage
working_directory: packages/<<parameters.package_name>>
workflows: workflows:
main:
jobs:
- yarn-monorepo
- go-lint-test-build:
name: batch-submitter-tests
binary_name: batch-submitter
working_directory: go/batch-submitter
- go-lint-test-build:
name: proxyd-tests
binary_name: proxyd
working_directory: go/proxyd
- go-lint-test-build:
name: teleportr-tests
binary_name: teleportr
working_directory: go/teleportr
- go-lint-test-build:
name: gas-oracle-tests
binary_name: gas-oracle
working_directory: go/gas-oracle
- go-lint-test-build:
name: indexer-tests
binary_name: indexer
working_directory: go/indexer
- go-lint-test:
name: bss-core-tests
working_directory: go/bss-core
- contracts-tests:
requires:
- yarn-monorepo
- js-lint-test:
name: dtl-tests
package_name: data-transport-layer
requires:
- yarn-monorepo
- js-lint-test:
name: core-utils-tests
package_name: core-utils
requires:
- yarn-monorepo
- js-lint-test:
name: sdk-tests
package_name: sdk
requires:
- yarn-monorepo
- js-lint-test:
name: message-relayer-tests
package_name: message-relayer
requires:
- yarn-monorepo
- js-lint-test:
name: replica-healthcheck-tests
package_name: replica-healthcheck
requires:
- yarn-monorepo
- depcheck:
requires:
- yarn-monorepo
- geth-tests
- integration-tests
nightly-itests: nightly-itests:
triggers: triggers:
- schedule: - schedule:
...@@ -252,7 +541,7 @@ workflows: ...@@ -252,7 +541,7 @@ workflows:
- develop - develop
jobs: jobs:
- build-dtl: - build-dtl:
context: context:
- optimism - optimism
- slack - slack
<<: *slack-nightly-build-fail-post-step <<: *slack-nightly-build-fail-post-step
...@@ -331,4 +620,4 @@ workflows: ...@@ -331,4 +620,4 @@ workflows:
} }
] ]
} }
event: always event: always
\ No newline at end of file
...@@ -50,7 +50,7 @@ jobs: ...@@ -50,7 +50,7 @@ jobs:
working-directory: ./ops working-directory: ./ops
run: | run: |
./scripts/stats.sh & ./scripts/stats.sh &
docker-compose -f docker-compose.yml up -d docker-compose -f docker-compose.yml up -d --scale replica-healthcheck=1
- name: Wait for the Sequencer node - name: Wait for the Sequencer node
working-directory: ./ops working-directory: ./ops
...@@ -64,7 +64,6 @@ jobs: ...@@ -64,7 +64,6 @@ jobs:
if: failure() if: failure()
uses: jwalton/gh-docker-logs@v1 uses: jwalton/gh-docker-logs@v1
with: with:
images: 'ethereumoptimism/hardhat,ops_deployer,ops_dtl,ops_l2geth,ethereumoptimism/message-relayer,ops_batch_submitter,ops_replica,ops_integration_tests'
dest: '/home/runner/logs' dest: '/home/runner/logs'
- name: Tar logs - name: Tar logs
......
...@@ -5,7 +5,7 @@ go 1.16 ...@@ -5,7 +5,7 @@ go 1.16
require ( require (
github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect
github.com/decred/dcrd/hdkeychain/v3 v3.0.0 github.com/decred/dcrd/hdkeychain/v3 v3.0.0
github.com/ethereum/go-ethereum v1.10.12 github.com/ethereum/go-ethereum v1.10.16
github.com/getsentry/sentry-go v0.11.0 github.com/getsentry/sentry-go v0.11.0
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.11.0
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
......
...@@ -115,8 +115,8 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 ...@@ -115,8 +115,8 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/base58 v1.0.3 h1:KGZuh8d1WEMIrK0leQRM47W85KqCAdl2N+uagbctdDI= github.com/decred/base58 v1.0.3 h1:KGZuh8d1WEMIrK0leQRM47W85KqCAdl2N+uagbctdDI=
github.com/decred/base58 v1.0.3/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbiSM78E= github.com/decred/base58 v1.0.3/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbiSM78E=
github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU=
...@@ -159,8 +159,8 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi ...@@ -159,8 +159,8 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/ethereum/go-ethereum v1.10.12 h1:el/KddB3gLEsnNgGQ3SQuZuiZjwnFTYHe5TwUet5Om4= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc=
github.com/ethereum/go-ethereum v1.10.12/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
...@@ -264,7 +264,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 ...@@ -264,7 +264,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
...@@ -300,8 +300,8 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/ ...@@ -300,8 +300,8 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
...@@ -322,7 +322,7 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 ...@@ -322,7 +322,7 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
......
...@@ -89,6 +89,12 @@ var ( ...@@ -89,6 +89,12 @@ var (
Usage: "length of epochs in seconds", Usage: "length of epochs in seconds",
EnvVar: "GAS_PRICE_ORACLE_EPOCH_LENGTH_SECONDS", EnvVar: "GAS_PRICE_ORACLE_EPOCH_LENGTH_SECONDS",
} }
L1BaseFeeEpochLengthSecondsFlag = cli.Uint64Flag{
Name: "l1-base-fee-epoch-length-seconds",
Value: 15,
Usage: "polling time for updating the L1 base fee",
EnvVar: "GAS_PRICE_ORACLE_L1_BASE_FEE_EPOCH_LENGTH_SECONDS",
}
L1BaseFeeSignificanceFactorFlag = cli.Float64Flag{ L1BaseFeeSignificanceFactorFlag = cli.Float64Flag{
Name: "l1-base-fee-significant-factor", Name: "l1-base-fee-significant-factor",
Value: 0.10, Value: 0.10,
...@@ -169,6 +175,7 @@ var Flags = []cli.Flag{ ...@@ -169,6 +175,7 @@ var Flags = []cli.Flag{
MaxPercentChangePerEpochFlag, MaxPercentChangePerEpochFlag,
AverageBlockGasLimitPerEpochFlag, AverageBlockGasLimitPerEpochFlag,
EpochLengthSecondsFlag, EpochLengthSecondsFlag,
L1BaseFeeEpochLengthSecondsFlag,
L2GasPriceSignificanceFactorFlag, L2GasPriceSignificanceFactorFlag,
WaitForReceiptFlag, WaitForReceiptFlag,
EnableL1BaseFeeFlag, EnableL1BaseFeeFlag,
......
...@@ -28,6 +28,7 @@ type Config struct { ...@@ -28,6 +28,7 @@ type Config struct {
maxPercentChangePerEpoch float64 maxPercentChangePerEpoch float64
averageBlockGasLimitPerEpoch uint64 averageBlockGasLimitPerEpoch uint64
epochLengthSeconds uint64 epochLengthSeconds uint64
l1BaseFeeEpochLengthSeconds uint64
l2GasPriceSignificanceFactor float64 l2GasPriceSignificanceFactor float64
l1BaseFeeSignificanceFactor float64 l1BaseFeeSignificanceFactor float64
enableL1BaseFee bool enableL1BaseFee bool
...@@ -54,6 +55,7 @@ func NewConfig(ctx *cli.Context) *Config { ...@@ -54,6 +55,7 @@ func NewConfig(ctx *cli.Context) *Config {
cfg.maxPercentChangePerEpoch = ctx.GlobalFloat64(flags.MaxPercentChangePerEpochFlag.Name) cfg.maxPercentChangePerEpoch = ctx.GlobalFloat64(flags.MaxPercentChangePerEpochFlag.Name)
cfg.averageBlockGasLimitPerEpoch = ctx.GlobalUint64(flags.AverageBlockGasLimitPerEpochFlag.Name) cfg.averageBlockGasLimitPerEpoch = ctx.GlobalUint64(flags.AverageBlockGasLimitPerEpochFlag.Name)
cfg.epochLengthSeconds = ctx.GlobalUint64(flags.EpochLengthSecondsFlag.Name) cfg.epochLengthSeconds = ctx.GlobalUint64(flags.EpochLengthSecondsFlag.Name)
cfg.l1BaseFeeEpochLengthSeconds = ctx.GlobalUint64(flags.L1BaseFeeEpochLengthSecondsFlag.Name)
cfg.l2GasPriceSignificanceFactor = ctx.GlobalFloat64(flags.L2GasPriceSignificanceFactorFlag.Name) cfg.l2GasPriceSignificanceFactor = ctx.GlobalFloat64(flags.L2GasPriceSignificanceFactorFlag.Name)
cfg.floorPrice = ctx.GlobalUint64(flags.FloorPriceFlag.Name) cfg.floorPrice = ctx.GlobalUint64(flags.FloorPriceFlag.Name)
cfg.l1BaseFeeSignificanceFactor = ctx.GlobalFloat64(flags.L1BaseFeeSignificanceFactorFlag.Name) cfg.l1BaseFeeSignificanceFactor = ctx.GlobalFloat64(flags.L1BaseFeeSignificanceFactorFlag.Name)
......
...@@ -111,6 +111,7 @@ func (g *GasPriceOracle) ensure() error { ...@@ -111,6 +111,7 @@ func (g *GasPriceOracle) ensure() error {
func (g *GasPriceOracle) Loop() { func (g *GasPriceOracle) Loop() {
timer := time.NewTicker(time.Duration(g.config.epochLengthSeconds) * time.Second) timer := time.NewTicker(time.Duration(g.config.epochLengthSeconds) * time.Second)
defer timer.Stop() defer timer.Stop()
for { for {
select { select {
case <-timer.C: case <-timer.C:
...@@ -126,7 +127,7 @@ func (g *GasPriceOracle) Loop() { ...@@ -126,7 +127,7 @@ func (g *GasPriceOracle) Loop() {
} }
func (g *GasPriceOracle) BaseFeeLoop() { func (g *GasPriceOracle) BaseFeeLoop() {
timer := time.NewTicker(15 * time.Second) timer := time.NewTicker(time.Duration(g.config.l1BaseFeeEpochLengthSeconds) * time.Second)
defer timer.Stop() defer timer.Stop()
updateBaseFee, err := wrapUpdateBaseFee(g.l1Backend, g.l2Backend, g.config) updateBaseFee, err := wrapUpdateBaseFee(g.l1Backend, g.l2Backend, g.config)
......
...@@ -38,38 +38,27 @@ func (d *Database) GetL1TokenByAddress(address string) (*Token, error) { ...@@ -38,38 +38,27 @@ func (d *Database) GetL1TokenByAddress(address string) (*Token, error) {
var token *Token var token *Token
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectL1TokenStatement) row := tx.QueryRow(selectL1TokenStatement, address)
if err != nil { if row.Err() != nil {
return err return row.Err()
}
rows, err := queryStmt.Query(address)
if err != nil {
return err
}
if !rows.Next() {
return nil
} }
var name string var name string
var symbol string var symbol string
var decimals uint8 var decimals uint8
err = rows.Scan(&name, &symbol, &decimals) err := row.Scan(&name, &symbol, &decimals)
if errors.Is(err, sql.ErrNoRows) {
return nil
}
if err != nil { if err != nil {
return err return err
} }
if rows.Next() {
return errors.New("address should be unique")
}
token = &Token{ token = &Token{
Name: name, Name: name,
Symbol: symbol, Symbol: symbol,
Decimals: decimals, Decimals: decimals,
} }
return nil return nil
}) })
if err != nil { if err != nil {
...@@ -88,32 +77,22 @@ func (d *Database) GetL2TokenByAddress(address string) (*Token, error) { ...@@ -88,32 +77,22 @@ func (d *Database) GetL2TokenByAddress(address string) (*Token, error) {
var token *Token var token *Token
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectL2TokenStatement) row := tx.QueryRow(selectL2TokenStatement, address)
if err != nil { if row.Err() != nil {
return err return row.Err()
}
rows, err := queryStmt.Query(address)
if err != nil {
return err
}
if !rows.Next() {
return nil
} }
var name string var name string
var symbol string var symbol string
var decimals uint8 var decimals uint8
err = rows.Scan(&name, &symbol, &decimals) err := row.Scan(&name, &symbol, &decimals)
if errors.Is(err, sql.ErrNoRows) {
return nil
}
if err != nil { if err != nil {
return err return err
} }
if rows.Next() {
return errors.New("address should be unique")
}
token = &Token{ token = &Token{
Name: name, Name: name,
Symbol: symbol, Symbol: symbol,
...@@ -141,22 +120,14 @@ func (d *Database) AddL1Token(address string, token *Token) error { ...@@ -141,22 +120,14 @@ func (d *Database) AddL1Token(address string, token *Token) error {
` `
return txn(d.db, func(tx *sql.Tx) error { return txn(d.db, func(tx *sql.Tx) error {
tokenStmt, err := tx.Prepare(insertTokenStatement) _, err := tx.Exec(
if err != nil { insertTokenStatement,
return err
}
_, err = tokenStmt.Exec(
address, address,
token.Name, token.Name,
token.Symbol, token.Symbol,
token.Decimals, token.Decimals,
) )
if err != nil { return err
return err
}
return nil
}) })
} }
...@@ -172,22 +143,14 @@ func (d *Database) AddL2Token(address string, token *Token) error { ...@@ -172,22 +143,14 @@ func (d *Database) AddL2Token(address string, token *Token) error {
` `
return txn(d.db, func(tx *sql.Tx) error { return txn(d.db, func(tx *sql.Tx) error {
tokenStmt, err := tx.Prepare(insertTokenStatement) _, err := tx.Exec(
if err != nil { insertTokenStatement,
return err
}
_, err = tokenStmt.Exec(
address, address,
token.Name, token.Name,
token.Symbol, token.Symbol,
token.Decimals, token.Decimals,
) )
if err != nil { return err
return err
}
return nil
}) })
} }
...@@ -209,12 +172,8 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { ...@@ -209,12 +172,8 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error {
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
` `
return txn(d.db, func(tx *sql.Tx) error { return txn(d.db, func(tx *sql.Tx) error {
blockStmt, err := tx.Prepare(insertBlockStatement) _, err := tx.Exec(
if err != nil { insertBlockStatement,
return err
}
_, err = blockStmt.Exec(
block.Hash.String(), block.Hash.String(),
block.ParentHash.String(), block.ParentHash.String(),
block.Number, block.Number,
...@@ -228,13 +187,9 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error { ...@@ -228,13 +187,9 @@ func (d *Database) AddIndexedL1Block(block *IndexedL1Block) error {
return nil return nil
} }
depositStmt, err := tx.Prepare(insertDepositStatement)
if err != nil {
return err
}
for _, deposit := range block.Deposits { for _, deposit := range block.Deposits {
_, err = depositStmt.Exec( _, err = tx.Exec(
insertDepositStatement,
NewGUID(), NewGUID(),
deposit.FromAddress.String(), deposit.FromAddress.String(),
deposit.ToAddress.String(), deposit.ToAddress.String(),
...@@ -273,12 +228,8 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { ...@@ -273,12 +228,8 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error {
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
` `
return txn(d.db, func(tx *sql.Tx) error { return txn(d.db, func(tx *sql.Tx) error {
blockStmt, err := tx.Prepare(insertBlockStatement) _, err := tx.Exec(
if err != nil { insertBlockStatement,
return err
}
_, err = blockStmt.Exec(
block.Hash.String(), block.Hash.String(),
block.ParentHash.String(), block.ParentHash.String(),
block.Number, block.Number,
...@@ -292,13 +243,9 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error { ...@@ -292,13 +243,9 @@ func (d *Database) AddIndexedL2Block(block *IndexedL2Block) error {
return nil return nil
} }
withdrawalStmt, err := tx.Prepare(insertWithdrawalStatement)
if err != nil {
return err
}
for _, withdrawal := range block.Withdrawals { for _, withdrawal := range block.Withdrawals {
_, err = withdrawalStmt.Exec( _, err = tx.Exec(
insertWithdrawalStatement,
NewGUID(), NewGUID(),
withdrawal.FromAddress.String(), withdrawal.FromAddress.String(),
withdrawal.ToAddress.String(), withdrawal.ToAddress.String(),
...@@ -330,13 +277,9 @@ func (d *Database) AddStateBatch(batches []StateBatch) error { ...@@ -330,13 +277,9 @@ func (d *Database) AddStateBatch(batches []StateBatch) error {
` `
return txn(d.db, func(tx *sql.Tx) error { return txn(d.db, func(tx *sql.Tx) error {
stateBatchStmt, err := tx.Prepare(insertStateBatchStatement)
if err != nil {
return err
}
for _, sb := range batches { for _, sb := range batches {
_, err = stateBatchStmt.Exec( _, err := tx.Exec(
insertStateBatchStatement,
sb.Index.Uint64(), sb.Index.Uint64(),
sb.Root.String(), sb.Root.String(),
sb.Size.Uint64(), sb.Size.Uint64(),
...@@ -371,15 +314,11 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP ...@@ -371,15 +314,11 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP
var deposits []DepositJSON var deposits []DepositJSON
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectDepositsStatement) rows, err := tx.Query(selectDepositsStatement, address.String(), page.Limit, page.Offset)
if err != nil {
return err
}
rows, err := queryStmt.Query(address.String(), page.Limit, page.Offset)
if err != nil { if err != nil {
return err return err
} }
defer rows.Close()
for rows.Next() { for rows.Next() {
var deposit DepositJSON var deposit DepositJSON
...@@ -397,9 +336,8 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP ...@@ -397,9 +336,8 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP
deposits = append(deposits, deposit) deposits = append(deposits, deposit)
} }
return nil return rows.Err()
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -414,21 +352,17 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP ...@@ -414,21 +352,17 @@ func (d *Database) GetDepositsByAddress(address common.Address, page PaginationP
` `
var count uint64 var count uint64
err = txn(d.db, func(tx *sql.Tx) error { err = txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectDepositCountStatement) row := tx.QueryRow(selectDepositCountStatement, address.String())
if err != nil { if err != nil {
return err return err
} }
row := queryStmt.QueryRow(address.String()) return row.Scan(&count)
if err != nil {
return err
}
row.Scan(&count)
return nil
}) })
if err != nil {
return nil, err
}
page.Total = count page.Total = count
...@@ -458,12 +392,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro ...@@ -458,12 +392,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro
var batch *StateBatchJSON var batch *StateBatchJSON
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectWithdrawalBatchStatement) row := tx.QueryRow(selectWithdrawalBatchStatement, hash.String())
if err != nil {
return err
}
row := queryStmt.QueryRow(hash.String())
if row.Err() != nil { if row.Err() != nil {
return row.Err() return row.Err()
} }
...@@ -471,7 +400,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro ...@@ -471,7 +400,7 @@ func (d *Database) GetWithdrawalBatch(hash l2common.Hash) (*StateBatchJSON, erro
var index, size, prevTotal, blockNumber, blockTimestamp uint64 var index, size, prevTotal, blockNumber, blockTimestamp uint64
var root, blockHash string var root, blockHash string
var extraData []byte var extraData []byte
err = row.Scan(&index, &root, &size, &prevTotal, &extraData, &blockHash, err := row.Scan(&index, &root, &size, &prevTotal, &extraData, &blockHash,
&blockNumber, &blockTimestamp) &blockNumber, &blockTimestamp)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
...@@ -519,15 +448,11 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina ...@@ -519,15 +448,11 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina
var withdrawals []WithdrawalJSON var withdrawals []WithdrawalJSON
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectWithdrawalsStatement) rows, err := tx.Query(selectWithdrawalsStatement, address.String(), page.Limit, page.Offset)
if err != nil {
return err
}
rows, err := queryStmt.Query(address.String(), page.Limit, page.Offset)
if err != nil { if err != nil {
return err return err
} }
defer rows.Close()
for rows.Next() { for rows.Next() {
var withdrawal WithdrawalJSON var withdrawal WithdrawalJSON
...@@ -545,7 +470,7 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina ...@@ -545,7 +470,7 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina
withdrawals = append(withdrawals, withdrawal) withdrawals = append(withdrawals, withdrawal)
} }
return nil return rows.Err()
}) })
if err != nil { if err != nil {
...@@ -567,21 +492,17 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina ...@@ -567,21 +492,17 @@ func (d *Database) GetWithdrawalsByAddress(address l2common.Address, page Pagina
` `
var count uint64 var count uint64
err = txn(d.db, func(tx *sql.Tx) error { err = txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectWithdrawalCountStatement) row := tx.QueryRow(selectWithdrawalCountStatement, address.String())
if err != nil {
return err
}
row := queryStmt.QueryRow(address.String())
if err != nil { if err != nil {
return err return err
} }
row.Scan(&count) return row.Scan(&count)
return nil
}) })
if err != nil {
return nil, err
}
page.Total = count page.Total = count
...@@ -599,19 +520,14 @@ func (d *Database) GetHighestL1Block() (*L1BlockLocator, error) { ...@@ -599,19 +520,14 @@ func (d *Database) GetHighestL1Block() (*L1BlockLocator, error) {
var highestBlock *L1BlockLocator var highestBlock *L1BlockLocator
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectHighestBlockStatement) row := tx.QueryRow(selectHighestBlockStatement)
if err != nil {
return err
}
row := queryStmt.QueryRow()
if row.Err() != nil { if row.Err() != nil {
return row.Err() return row.Err()
} }
var number uint64 var number uint64
var hash string var hash string
err = row.Scan(&number, &hash) err := row.Scan(&number, &hash)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
highestBlock = nil highestBlock = nil
...@@ -642,19 +558,14 @@ func (d *Database) GetHighestL2Block() (*L2BlockLocator, error) { ...@@ -642,19 +558,14 @@ func (d *Database) GetHighestL2Block() (*L2BlockLocator, error) {
var highestBlock *L2BlockLocator var highestBlock *L2BlockLocator
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectHighestBlockStatement) row := tx.QueryRow(selectHighestBlockStatement)
if err != nil {
return err
}
row := queryStmt.QueryRow()
if row.Err() != nil { if row.Err() != nil {
return row.Err() return row.Err()
} }
var number uint64 var number uint64
var hash string var hash string
err = row.Scan(&number, &hash) err := row.Scan(&number, &hash)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
highestBlock = nil highestBlock = nil
...@@ -688,25 +599,20 @@ func (d *Database) GetIndexedL1BlockByHash(hash common.Hash) (*IndexedL1Block, e ...@@ -688,25 +599,20 @@ func (d *Database) GetIndexedL1BlockByHash(hash common.Hash) (*IndexedL1Block, e
var block *IndexedL1Block var block *IndexedL1Block
err := txn(d.db, func(tx *sql.Tx) error { err := txn(d.db, func(tx *sql.Tx) error {
queryStmt, err := tx.Prepare(selectBlockByHashStatement) row := tx.QueryRow(selectBlockByHashStatement, hash.String())
if err != nil {
return err
}
row := queryStmt.QueryRow(hash.String())
if errors.Is(row.Err(), sql.ErrNoRows) {
return nil
}
if row.Err() != nil { if row.Err() != nil {
return err return row.Err()
} }
var hash string var hash string
var parentHash string var parentHash string
var number uint64 var number uint64
var timestamp uint64 var timestamp uint64
err = row.Scan(&hash, &parentHash, &number, &timestamp) err := row.Scan(&hash, &parentHash, &number, &timestamp)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil
}
return err return err
} }
......
...@@ -2,12 +2,13 @@ package metrics ...@@ -2,12 +2,13 @@ package metrics
import ( import (
"fmt" "fmt"
"net/http"
l2common "github.com/ethereum-optimism/optimism/l2geth/common" l2common "github.com/ethereum-optimism/optimism/l2geth/common"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"net/http"
) )
const metricsNamespace = "indexer" const metricsNamespace = "indexer"
......
...@@ -2,6 +2,7 @@ package bridge ...@@ -2,6 +2,7 @@ package bridge
import ( import (
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/go/indexer/bindings/address_manager" "github.com/ethereum-optimism/optimism/go/indexer/bindings/address_manager"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
......
...@@ -2,6 +2,7 @@ package bridge ...@@ -2,6 +2,7 @@ package bridge
import ( import (
"context" "context"
"github.com/ethereum-optimism/optimism/go/indexer/bindings/l1bridge" "github.com/ethereum-optimism/optimism/go/indexer/bindings/l1bridge"
"github.com/ethereum-optimism/optimism/go/indexer/db" "github.com/ethereum-optimism/optimism/go/indexer/db"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
......
...@@ -2,6 +2,7 @@ package l1 ...@@ -2,6 +2,7 @@ package l1
import ( import (
"context" "context"
"github.com/ethereum-optimism/optimism/go/indexer/bindings/l1erc20" "github.com/ethereum-optimism/optimism/go/indexer/bindings/l1erc20"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
...@@ -40,7 +41,6 @@ func QueryERC20(address common.Address, client *ethclient.Client) (*db.Token, er ...@@ -40,7 +41,6 @@ func QueryERC20(address common.Address, client *ethclient.Client) (*db.Token, er
}, nil }, nil
} }
func QueryStateBatches(filterer *scc.StateCommitmentChainFilterer, startHeight, endHeight uint64, ctx context.Context) (map[common.Hash][]db.StateBatch, error) { func QueryStateBatches(filterer *scc.StateCommitmentChainFilterer, startHeight, endHeight uint64, ctx context.Context) (map[common.Hash][]db.StateBatch, error) {
batches := make(map[common.Hash][]db.StateBatch) batches := make(map[common.Hash][]db.StateBatch)
......
...@@ -3,6 +3,6 @@ module github.com/ethereum-optimism/optimism/go/l2geth-exporter ...@@ -3,6 +3,6 @@ module github.com/ethereum-optimism/optimism/go/l2geth-exporter
go 1.16 go 1.16
require ( require (
github.com/ethereum/go-ethereum v1.10.8 github.com/ethereum/go-ethereum v1.10.16
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.11.0
) )
...@@ -37,6 +37,7 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q ...@@ -37,6 +37,7 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
...@@ -74,6 +75,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE ...@@ -74,6 +75,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
...@@ -87,32 +89,38 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h ...@@ -87,32 +89,38 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.10.8 h1:0UP5WUR8hh46ffbjJV7PK499+uGEyasRIfffS0vy06o= github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZUGLEaoc=
github.com/ethereum/go-ethereum v1.10.8/go.mod h1:pJNuIUYfX5+JKzSD/BTdNsvJSZ1TJqmz0dVyXMAbf6M= github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
...@@ -132,7 +140,7 @@ github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= ...@@ -132,7 +140,7 @@ github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
...@@ -159,8 +167,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw ...@@ -159,8 +167,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
...@@ -171,6 +180,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw ...@@ -171,6 +180,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
...@@ -187,13 +197,19 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR ...@@ -187,13 +197,19 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI=
github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
...@@ -209,7 +225,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y ...@@ -209,7 +225,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
...@@ -227,7 +244,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V ...@@ -227,7 +244,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
...@@ -239,8 +256,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv ...@@ -239,8 +256,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
...@@ -252,19 +271,26 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG ...@@ -252,19 +271,26 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
...@@ -276,6 +302,7 @@ github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h ...@@ -276,6 +302,7 @@ github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
...@@ -294,8 +321,10 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG ...@@ -294,8 +321,10 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
...@@ -318,11 +347,13 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT ...@@ -318,11 +347,13 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
...@@ -340,6 +371,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO ...@@ -340,6 +371,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
...@@ -348,13 +380,16 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf ...@@ -348,13 +380,16 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
...@@ -447,6 +482,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ ...@@ -447,6 +482,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
...@@ -499,10 +535,12 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= ...@@ -499,10 +535,12 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
...@@ -534,6 +572,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= ...@@ -534,6 +572,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
...@@ -584,12 +623,14 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks ...@@ -584,12 +623,14 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
...@@ -599,6 +640,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= ...@@ -599,6 +640,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
......
...@@ -255,7 +255,7 @@ func (b *Backend) ProxyWS(clientConn *websocket.Conn, methodWhitelist *StringSet ...@@ -255,7 +255,7 @@ func (b *Backend) ProxyWS(clientConn *websocket.Conn, methodWhitelist *StringSet
return nil, ErrBackendOverCapacity return nil, ErrBackendOverCapacity
} }
backendConn, _, err := b.dialer.Dial(b.wsURL, nil) backendConn, _, err := b.dialer.Dial(b.wsURL, nil) // nolint:bodyclose
if err != nil { if err != nil {
b.setOffline() b.setOffline()
if err := b.rateLimiter.DecBackendWSConns(b.Name); err != nil { if err := b.rateLimiter.DecBackendWSConns(b.Name); err != nil {
...@@ -513,7 +513,9 @@ func (w *WSProxier) clientPump(ctx context.Context, errC chan error) { ...@@ -513,7 +513,9 @@ func (w *WSProxier) clientPump(ctx context.Context, errC chan error) {
msgType, msg, err := w.clientConn.ReadMessage() msgType, msg, err := w.clientConn.ReadMessage()
if err != nil { if err != nil {
errC <- err errC <- err
outConn.WriteMessage(websocket.CloseMessage, formatWSError(err)) if err := outConn.WriteMessage(websocket.CloseMessage, formatWSError(err)); err != nil {
log.Error("error writing backendConn message", "err", err)
}
return return
} }
...@@ -575,7 +577,9 @@ func (w *WSProxier) backendPump(ctx context.Context, errC chan error) { ...@@ -575,7 +577,9 @@ func (w *WSProxier) backendPump(ctx context.Context, errC chan error) {
msgType, msg, err := w.backendConn.ReadMessage() msgType, msg, err := w.backendConn.ReadMessage()
if err != nil { if err != nil {
errC <- err errC <- err
w.clientConn.WriteMessage(websocket.CloseMessage, formatWSError(err)) if err := w.clientConn.WriteMessage(websocket.CloseMessage, formatWSError(err)); err != nil {
log.Error("error writing clientConn message", "err", err)
}
return return
} }
......
...@@ -3,12 +3,13 @@ package integration_tests ...@@ -3,12 +3,13 @@ package integration_tests
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/alicebob/miniredis"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/alicebob/miniredis"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
) )
func TestCaching(t *testing.T) { func TestCaching(t *testing.T) {
......
...@@ -2,13 +2,14 @@ package integration_tests ...@@ -2,13 +2,14 @@ package integration_tests
import ( import (
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
"net/http" "net/http"
"os" "os"
"sync/atomic" "sync/atomic"
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
) )
const ( const (
...@@ -39,7 +40,7 @@ func TestFailover(t *testing.T) { ...@@ -39,7 +40,7 @@ func TestFailover(t *testing.T) {
"backend responds 200 with non-JSON response", "backend responds 200 with non-JSON response",
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("this data is not JSON!")) _, _ = w.Write([]byte("this data is not JSON!"))
}), }),
}, },
{ {
...@@ -87,7 +88,7 @@ func TestFailover(t *testing.T) { ...@@ -87,7 +88,7 @@ func TestFailover(t *testing.T) {
t.Run("backend times out and falls back to another", func(t *testing.T) { t.Run("backend times out and falls back to another", func(t *testing.T) {
badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
w.Write([]byte("{}")) _, _ = w.Write([]byte("{}"))
})) }))
res, statusCode, err := client.SendRPC("eth_chainId", nil) res, statusCode, err := client.SendRPC("eth_chainId", nil)
require.NoError(t, err) require.NoError(t, err)
...@@ -133,7 +134,7 @@ func TestRetries(t *testing.T) { ...@@ -133,7 +134,7 @@ func TestRetries(t *testing.T) {
w.WriteHeader(500) w.WriteHeader(500)
return return
} }
w.Write([]byte(goodResponse)) _, _ = w.Write([]byte(goodResponse))
})) }))
// test case where request eventually succeeds // test case where request eventually succeeds
...@@ -169,7 +170,7 @@ func TestOutOfServiceInterval(t *testing.T) { ...@@ -169,7 +170,7 @@ func TestOutOfServiceInterval(t *testing.T) {
defer shutdown() defer shutdown()
okHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { okHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(goodResponse)) _, _ = w.Write([]byte(goodResponse))
}) })
badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(503) w.WriteHeader(503)
...@@ -190,10 +191,12 @@ func TestOutOfServiceInterval(t *testing.T) { ...@@ -190,10 +191,12 @@ func TestOutOfServiceInterval(t *testing.T) {
require.Equal(t, 2, len(badBackend.Requests())) require.Equal(t, 2, len(badBackend.Requests()))
require.Equal(t, 2, len(goodBackend.Requests())) require.Equal(t, 2, len(goodBackend.Requests()))
res, statusCode, err = client.SendBatchRPC( _, statusCode, err = client.SendBatchRPC(
NewRPCReq("1", "eth_chainId", nil), NewRPCReq("1", "eth_chainId", nil),
NewRPCReq("1", "eth_chainId", nil), NewRPCReq("1", "eth_chainId", nil),
) )
require.NoError(t, err)
require.Equal(t, 200, statusCode)
require.Equal(t, 2, len(badBackend.Requests())) require.Equal(t, 2, len(badBackend.Requests()))
require.Equal(t, 4, len(goodBackend.Requests())) require.Equal(t, 4, len(goodBackend.Requests()))
......
...@@ -4,11 +4,12 @@ import ( ...@@ -4,11 +4,12 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"github.com/ethereum-optimism/optimism/go/proxyd"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"sync" "sync"
"github.com/ethereum-optimism/optimism/go/proxyd"
) )
type RecordedRequest struct { type RecordedRequest struct {
...@@ -27,7 +28,7 @@ type MockBackend struct { ...@@ -27,7 +28,7 @@ type MockBackend struct {
func SingleResponseHandler(code int, response string) http.HandlerFunc { func SingleResponseHandler(code int, response string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(code) w.WriteHeader(code)
w.Write([]byte(response)) _, _ = w.Write([]byte(response))
} }
} }
......
package integration_tests package integration_tests
import ( import (
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
"os" "os"
"testing" "testing"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
) )
type resWithCode struct { type resWithCode struct {
......
...@@ -4,12 +4,13 @@ import ( ...@@ -4,12 +4,13 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/BurntSushi/toml"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"testing" "testing"
"github.com/BurntSushi/toml"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
) )
type ProxydClient struct { type ProxydClient struct {
......
package integration_tests package integration_tests
import ( import (
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/ethereum-optimism/optimism/go/proxyd"
"github.com/stretchr/testify/require"
) )
const ( const (
......
...@@ -217,7 +217,11 @@ func Start(config *Config) (func(), error) { ...@@ -217,7 +217,11 @@ func Start(config *Config) (func(), error) {
if config.Metrics.Enabled { if config.Metrics.Enabled {
addr := fmt.Sprintf("%s:%d", config.Metrics.Host, config.Metrics.Port) addr := fmt.Sprintf("%s:%d", config.Metrics.Host, config.Metrics.Port)
log.Info("starting metrics server", "addr", addr) log.Info("starting metrics server", "addr", addr)
go http.ListenAndServe(addr, promhttp.Handler()) go func() {
if err := http.ListenAndServe(addr, promhttp.Handler()); err != nil {
log.Error("error starting metrics server", "err", err)
}
}()
} }
// To allow integration tests to cleanly come up, wait // To allow integration tests to cleanly come up, wait
......
...@@ -5,10 +5,11 @@ import ( ...@@ -5,10 +5,11 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/log"
"github.com/go-redis/redis/v8"
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/log"
"github.com/go-redis/redis/v8"
) )
const MaxRPSScript = ` const MaxRPSScript = `
......
...@@ -2,8 +2,9 @@ package proxyd ...@@ -2,8 +2,9 @@ package proxyd
import ( import (
"encoding/json" "encoding/json"
"github.com/stretchr/testify/require"
"testing" "testing"
"github.com/stretchr/testify/require"
) )
func TestRPCResJSON(t *testing.T) { func TestRPCResJSON(t *testing.T) {
......
...@@ -107,15 +107,15 @@ func (s *Server) WSListenAndServe(host string, port int) error { ...@@ -107,15 +107,15 @@ func (s *Server) WSListenAndServe(host string, port int) error {
func (s *Server) Shutdown() { func (s *Server) Shutdown() {
if s.rpcServer != nil { if s.rpcServer != nil {
s.rpcServer.Shutdown(context.Background()) _ = s.rpcServer.Shutdown(context.Background())
} }
if s.wsServer != nil { if s.wsServer != nil {
s.wsServer.Shutdown(context.Background()) _ = s.wsServer.Shutdown(context.Background())
} }
} }
func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) { func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK")) _, _ = w.Write([]byte("OK"))
} }
func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
...@@ -159,7 +159,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { ...@@ -159,7 +159,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
return return
} }
batchRes := make([]*RPCRes, len(reqs), len(reqs)) batchRes := make([]*RPCRes, len(reqs))
var batchContainsCached bool var batchContainsCached bool
for i := 0; i < len(reqs); i++ { for i := 0; i < len(reqs); i++ {
req, err := ParseRPCReq(reqs[i]) req, err := ParseRPCReq(reqs[i])
...@@ -301,7 +301,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context ...@@ -301,7 +301,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context
} }
return context.WithValue( return context.WithValue(
r.Context(), r.Context(),
ContextKeyReqID, ContextKeyReqID, // nolint:staticcheck
randStr(10), randStr(10),
) )
} }
...@@ -321,11 +321,11 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context ...@@ -321,11 +321,11 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context
} }
} }
ctx := context.WithValue(r.Context(), ContextKeyAuth, s.authenticatedPaths[authorization]) ctx := context.WithValue(r.Context(), ContextKeyAuth, s.authenticatedPaths[authorization]) // nolint:staticcheck
ctx = context.WithValue(ctx, ContextKeyXForwardedFor, xff) ctx = context.WithValue(ctx, ContextKeyXForwardedFor, xff) // nolint:staticcheck
return context.WithValue( return context.WithValue(
ctx, ctx,
ContextKeyReqID, ContextKeyReqID, // nolint:staticcheck
randStr(10), randStr(10),
) )
} }
...@@ -413,17 +413,6 @@ func GetXForwardedFor(ctx context.Context) string { ...@@ -413,17 +413,6 @@ func GetXForwardedFor(ctx context.Context) string {
return xff return xff
} }
type recordLenReader struct {
io.Reader
Len int
}
func (r *recordLenReader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
r.Len += n
return
}
type recordLenWriter struct { type recordLenWriter struct {
io.Writer io.Writer
Len int Len int
......
...@@ -142,15 +142,15 @@ func NewConfig(ctx *cli.Context) (Config, error) { ...@@ -142,15 +142,15 @@ func NewConfig(ctx *cli.Context) (Config, error) {
return Config{ return Config{
Hostname: ctx.GlobalString(flags.APIHostnameFlag.Name), Hostname: ctx.GlobalString(flags.APIHostnameFlag.Name),
Port: uint16(ctx.GlobalUint64(flags.APIPortFlag.Name)), Port: uint16(ctx.GlobalUint64(flags.APIPortFlag.Name)),
L1EthRpc: ctx.GlobalString(flags.APIL1EthRpcFlag.Name), L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name),
DepositAddress: ctx.GlobalString(flags.APIDepositAddressFlag.Name), DepositAddress: ctx.GlobalString(flags.DepositAddressFlag.Name),
NumConfirmations: ctx.GlobalUint64(flags.APINumConfirmationsFlag.Name), NumConfirmations: ctx.GlobalUint64(flags.NumDepositConfirmationsFlag.Name),
PostgresHost: ctx.GlobalString(flags.APIPostgresHostFlag.Name), PostgresHost: ctx.GlobalString(flags.PostgresHostFlag.Name),
PostgresPort: uint16(ctx.GlobalUint64(flags.APIPostgresPortFlag.Name)), PostgresPort: uint16(ctx.GlobalUint64(flags.PostgresPortFlag.Name)),
PostgresUser: ctx.GlobalString(flags.APIPostgresUserFlag.Name), PostgresUser: ctx.GlobalString(flags.PostgresUserFlag.Name),
PostgresPassword: ctx.GlobalString(flags.APIPostgresPasswordFlag.Name), PostgresPassword: ctx.GlobalString(flags.PostgresPasswordFlag.Name),
PostgresDBName: ctx.GlobalString(flags.APIPostgresDBNameFlag.Name), PostgresDBName: ctx.GlobalString(flags.PostgresDBNameFlag.Name),
PostgresEnableSSL: ctx.GlobalBool(flags.APIPostgresEnableSSLFlag.Name), PostgresEnableSSL: ctx.GlobalBool(flags.PostgresEnableSSLFlag.Name),
}, nil }, nil
} }
......
...@@ -37,7 +37,7 @@ type TeleportrDisburserDisbursement struct { ...@@ -37,7 +37,7 @@ type TeleportrDisburserDisbursement struct {
// TeleportrDisburserMetaData contains all meta data concerning the TeleportrDisburser contract. // TeleportrDisburserMetaData contains all meta data concerning the TeleportrDisburser contract.
var TeleportrDisburserMetaData = &bind.MetaData{ var TeleportrDisburserMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"BalanceWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementSuccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nextDepositId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"internalType\":\"structTeleportrDisburser.Disbursement[]\",\"name\":\"_disbursements\",\"type\":\"tuple[]\"}],\"name\":\"disburse\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDisbursements\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"BalanceWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementSuccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nextDepositId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"internalType\":\"structTeleportrDisburser.Disbursement[]\",\"name\":\"_disbursements\",\"type\":\"tuple[]\"}],\"name\":\"disburse\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDisbursements\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b5061001a33610024565b6000600155610074565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6109e1806100836000396000f3fe6080604052600436106100655760003560e01c80638da5cb5b116100435780638da5cb5b146100bf578063ad48144d146100f4578063f2fde38b1461010757600080fd5b806325999e7f1461006a5780635fd8c71014610093578063715018a6146100aa575b600080fd5b34801561007657600080fd5b5061008060015481565b6040519081526020015b60405180910390f35b34801561009f57600080fd5b506100a8610127565b005b3480156100b657600080fd5b506100a8610248565b3480156100cb57600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b6100a8610102366004610840565b6102d5565b34801561011357600080fd5b506100a86101223660046108bf565b61069b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6000546040805147808252915173ffffffffffffffffffffffffffffffffffffffff9093169283917fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f1919081900360200190a260405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610243573d6000803e3d6000fd5b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b6102d360006107cb565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b80806103be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f2064697362757273656d656e74730000000000000000000000000000000060448201526064016101a4565b60015484811461042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e6578706563746564206e657874206465706f73697420696400000000000060448201526064016101a4565b60018054830190556000805b8381101561047757858582818110610450576104506108fc565b610463926040909102013590508361095a565b91508061046f81610972565b915050610436565b50348114610507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f44697362757273656d656e7420746f74616c20213d20616d6f756e742073656e60448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016101a4565b60005b83811015610692576000868683818110610526576105266108fc565b9050604002016000013590506000878784818110610546576105466108fc565b905060400201602001602081019061055e91906108bf565b905060008173ffffffffffffffffffffffffffffffffffffffff16836108fc90604051600060405180830381858888f193505050503d80600081146105bf576040519150601f19603f3d011682016040523d82523d6000602084013e6105c4565b606091505b505090508015610624578173ffffffffffffffffffffffffffffffffffffffff16867feaa22fd2d7b875476355b32cf719794faf9d91b66e73bc6375a053cace9caaee8560405161061791815260200190565b60405180910390a3610676565b8173ffffffffffffffffffffffffffffffffffffffff16867f9b478c095979d3d3a7d602ffd9ee1f0843204d853558ae0882c8fcc0a5bc78cf8560405161066d91815260200190565b60405180910390a35b600186019550505050808061068a90610972565b91505061050a565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461071c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b73ffffffffffffffffffffffffffffffffffffffff81166107bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101a4565b6107c8816107cb565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060006040848603121561085557600080fd5b83359250602084013567ffffffffffffffff8082111561087457600080fd5b818601915086601f83011261088857600080fd5b81358181111561089757600080fd5b8760208260061b85010111156108ac57600080fd5b6020830194508093505050509250925092565b6000602082840312156108d157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561096d5761096d61092b565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156109a4576109a461092b565b506001019056fea2646970667358221220955e65ceaae72ce1d31ed14064916aa5576cb375d1a20fa0959e5a0d69e361fc64736f6c63430008090033", Bin: "0x608060405234801561001057600080fd5b5061001a33610024565b6000600155610074565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6109e1806100836000396000f3fe6080604052600436106100655760003560e01c80638da5cb5b116100435780638da5cb5b146100bf578063ad48144d146100f4578063f2fde38b1461010757600080fd5b806325999e7f1461006a5780635fd8c71014610093578063715018a6146100aa575b600080fd5b34801561007657600080fd5b5061008060015481565b6040519081526020015b60405180910390f35b34801561009f57600080fd5b506100a8610127565b005b3480156100b657600080fd5b506100a8610248565b3480156100cb57600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008a565b6100a8610102366004610840565b6102d5565b34801561011357600080fd5b506100a86101223660046108bf565b61069b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6000546040805147808252915173ffffffffffffffffffffffffffffffffffffffff9093169283917fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f1919081900360200190a260405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610243573d6000803e3d6000fd5b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b6102d360006107cb565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b80806103be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4e6f2064697362757273656d656e74730000000000000000000000000000000060448201526064016101a4565b60015484811461042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e6578706563746564206e657874206465706f73697420696400000000000060448201526064016101a4565b60018054830190556000805b8381101561047757858582818110610450576104506108fc565b610463926040909102013590508361095a565b91508061046f81610972565b915050610436565b50348114610507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f44697362757273656d656e7420746f74616c20213d20616d6f756e742073656e60448201527f740000000000000000000000000000000000000000000000000000000000000060648201526084016101a4565b60005b83811015610692576000868683818110610526576105266108fc565b9050604002016000013590506000878784818110610546576105466108fc565b905060400201602001602081019061055e91906108bf565b905060008173ffffffffffffffffffffffffffffffffffffffff16836108fc90604051600060405180830381858888f193505050503d80600081146105bf576040519150601f19603f3d011682016040523d82523d6000602084013e6105c4565b606091505b505090508015610624578173ffffffffffffffffffffffffffffffffffffffff16867feaa22fd2d7b875476355b32cf719794faf9d91b66e73bc6375a053cace9caaee8560405161061791815260200190565b60405180910390a3610676565b8173ffffffffffffffffffffffffffffffffffffffff16867f9b478c095979d3d3a7d602ffd9ee1f0843204d853558ae0882c8fcc0a5bc78cf8560405161066d91815260200190565b60405180910390a35b600186019550505050808061068a90610972565b91505061050a565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461071c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a4565b73ffffffffffffffffffffffffffffffffffffffff81166107bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101a4565b6107c8816107cb565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060006040848603121561085557600080fd5b83359250602084013567ffffffffffffffff8082111561087457600080fd5b818601915086601f83011261088857600080fd5b81358181111561089757600080fd5b8760208260061b85010111156108ac57600080fd5b6020830194508093505050509250925092565b6000602082840312156108d157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561096d5761096d61092b565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156109a4576109a461092b565b506001019056fea26469706673582212209c98cb9cc04bc2bf5e8c0baf23ef87d045122afe6cfbb0e3c31bd854dd7fad7d64736f6c63430008090033",
} }
// TeleportrDisburserABI is the input ABI used to generate the binding from. // TeleportrDisburserABI is the input ABI used to generate the binding from.
......
...@@ -33,6 +33,13 @@ func main() { ...@@ -33,6 +33,13 @@ func main() {
app.Name = "teleportr" app.Name = "teleportr"
app.Usage = "Teleportr" app.Usage = "Teleportr"
app.Description = "Teleportr bridge from L1 to L2" app.Description = "Teleportr bridge from L1 to L2"
app.Commands = []cli.Command{
{
Name: "migrate",
Usage: "Migrates teleportr's database",
Action: teleportr.Migrate(),
},
}
app.Action = teleportr.Main(GitVersion) app.Action = teleportr.Main(GitVersion)
err := app.Run(os.Args) err := app.Run(os.Args)
......
...@@ -390,7 +390,8 @@ dep.txn_hash, dep.block_number, dep.block_timestamp, ...@@ -390,7 +390,8 @@ dep.txn_hash, dep.block_number, dep.block_timestamp,
dis.txn_hash, dis.block_number, dis.block_timestamp dis.txn_hash, dis.block_number, dis.block_timestamp
FROM deposits AS dep FROM deposits AS dep
LEFT JOIN disbursements AS dis LEFT JOIN disbursements AS dis
ON dep.id = dis.id AND dep.txn_hash = $1 ON dep.id = dis.id
WHERE dep.txn_hash = $1
LIMIT 1 LIMIT 1
` `
...@@ -416,7 +417,8 @@ dep.txn_hash, dep.block_number, dep.block_timestamp, ...@@ -416,7 +417,8 @@ dep.txn_hash, dep.block_number, dep.block_timestamp,
dis.txn_hash, dis.block_number, dis.block_timestamp dis.txn_hash, dis.block_number, dis.block_timestamp
FROM deposits AS dep FROM deposits AS dep
LEFT JOIN disbursements AS dis LEFT JOIN disbursements AS dis
ON dep.id = dis.id AND dep.address = $1 ON dep.id = dis.id
WHERE dep.address = $1
ORDER BY dep.block_timestamp DESC, dep.id DESC ORDER BY dep.block_timestamp DESC, dep.id DESC
LIMIT 100 LIMIT 100
` `
......
...@@ -139,6 +139,9 @@ func (d *Driver) ClearPendingTx( ...@@ -139,6 +139,9 @@ func (d *Driver) ClearPendingTx(
func (d *Driver) GetBatchBlockRange( func (d *Driver) GetBatchBlockRange(
ctx context.Context) (*big.Int, *big.Int, error) { ctx context.Context) (*big.Int, *big.Int, error) {
// Update balance metrics on each iteration.
d.updateBalanceMetrics(ctx)
// Clear the current deposit IDs from any prior iteration. // Clear the current deposit IDs from any prior iteration.
d.currentDepositIDs = nil d.currentDepositIDs = nil
...@@ -234,6 +237,7 @@ func (d *Driver) CraftBatchTx( ...@@ -234,6 +237,7 @@ func (d *Driver) CraftBatchTx(
var disbursements []disburse.TeleportrDisburserDisbursement var disbursements []disburse.TeleportrDisburserDisbursement
var depositIDs []uint64 var depositIDs []uint64
value := new(big.Int)
for _, deposit := range confirmedDeposits { for _, deposit := range confirmedDeposits {
disbursement := disburse.TeleportrDisburserDisbursement{ disbursement := disburse.TeleportrDisburserDisbursement{
Amount: deposit.Amount, Amount: deposit.Amount,
...@@ -241,6 +245,7 @@ func (d *Driver) CraftBatchTx( ...@@ -241,6 +245,7 @@ func (d *Driver) CraftBatchTx(
} }
disbursements = append(disbursements, disbursement) disbursements = append(disbursements, disbursement)
depositIDs = append(depositIDs, deposit.ID) depositIDs = append(depositIDs, deposit.ID)
value = value.Add(value, deposit.Amount)
} }
log.Info(name+" crafting batch tx", "start", start, "end", end, log.Info(name+" crafting batch tx", "start", start, "end", end,
...@@ -250,7 +255,7 @@ func (d *Driver) CraftBatchTx( ...@@ -250,7 +255,7 @@ func (d *Driver) CraftBatchTx(
log.Info(name+" batch constructed", "num_disbursements", len(disbursements)) log.Info(name+" batch constructed", "num_disbursements", len(disbursements))
gasPrice, err := d.cfg.L1Client.SuggestGasPrice(ctx) gasPrice, err := d.cfg.L2Client.SuggestGasPrice(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -265,6 +270,7 @@ func (d *Driver) CraftBatchTx( ...@@ -265,6 +270,7 @@ func (d *Driver) CraftBatchTx(
opts.Nonce = nonce opts.Nonce = nonce
opts.GasPrice = gasPrice opts.GasPrice = gasPrice
opts.NoSend = true opts.NoSend = true
opts.Value = value
tx, err := d.disburserContract.Disburse(opts, start, disbursements) tx, err := d.disburserContract.Disburse(opts, start, disbursements)
if err != nil { if err != nil {
...@@ -299,6 +305,7 @@ func (d *Driver) UpdateGasPrice( ...@@ -299,6 +305,7 @@ func (d *Driver) UpdateGasPrice(
opts.Context = ctx opts.Context = ctx
opts.Nonce = new(big.Int).SetUint64(tx.Nonce()) opts.Nonce = new(big.Int).SetUint64(tx.Nonce())
opts.GasPrice = gasPrice opts.GasPrice = gasPrice
opts.Value = tx.Value()
opts.NoSend = true opts.NoSend = true
return d.rawDisburserContract.RawTransact(opts, tx.Data()) return d.rawDisburserContract.RawTransact(opts, tx.Data())
...@@ -313,7 +320,7 @@ func (d *Driver) SendTransaction( ...@@ -313,7 +320,7 @@ func (d *Driver) SendTransaction(
txHash := tx.Hash() txHash := tx.Hash()
startID := d.currentDepositIDs[0] startID := d.currentDepositIDs[0]
endID := d.currentDepositIDs[len(d.currentDepositIDs)] + 1 endID := d.currentDepositIDs[len(d.currentDepositIDs)-1] + 1
// Record the pending transaction hash so that we can recover if we crash // Record the pending transaction hash so that we can recover if we crash
// after publishing. // after publishing.
...@@ -426,10 +433,10 @@ func (d *Driver) processPendingTxs(ctx context.Context) error { ...@@ -426,10 +433,10 @@ func (d *Driver) processPendingTxs(ctx context.Context) error {
"blockTimestamp", blockTimestamp) "blockTimestamp", blockTimestamp)
} }
d.metrics.SuccessfulDisbursements.Set(float64(successfulDisbursements)) d.metrics.SuccessfulDisbursements.Add(float64(successfulDisbursements))
d.metrics.FailedDisbursements.Set(float64(failedDisbursements)) d.metrics.FailedDisbursements.Add(float64(failedDisbursements))
d.metrics.FailedDatabaseMethods.With(DBMethodUpsertDisbursement). d.metrics.FailedDatabaseMethods.With(DBMethodUpsertDisbursement).
Set(float64(failedUpserts)) Inc()
// We have completed our post-processing once all of the disbursements are // We have completed our post-processing once all of the disbursements are
// written without failures. // written without failures.
...@@ -616,7 +623,7 @@ func (d *Driver) logDatabaseContractMismatch( ...@@ -616,7 +623,7 @@ func (d *Driver) logDatabaseContractMismatch(
log.Warn("Recorded disbursements behind contract", log.Warn("Recorded disbursements behind contract",
"last_disbursement_id", *lastDisbursementID, "last_disbursement_id", *lastDisbursementID,
"contract_next_id", contractNextID) "contract_next_id", contractNextID)
d.metrics.DepositIDMismatch.Set(1.0) d.metrics.DepositIDMismatch.Inc()
// The last recorded disbursement is ahead of what the contract believes. // The last recorded disbursement is ahead of what the contract believes.
// This should NEVER happen unless the sequencer blows up and loses // This should NEVER happen unless the sequencer blows up and loses
...@@ -639,7 +646,7 @@ func (d *Driver) logDatabaseContractMismatch( ...@@ -639,7 +646,7 @@ func (d *Driver) logDatabaseContractMismatch(
log.Warn("Recorded disbursements behind contract", log.Warn("Recorded disbursements behind contract",
"last_disbursement_id", nil, "last_disbursement_id", nil,
"contract_next_id", contractNextID) "contract_next_id", contractNextID)
d.metrics.DepositIDMismatch.Set(1.0) d.metrics.DepositIDMismatch.Inc()
// Database and contract indicate we have not done a disbursement. // Database and contract indicate we have not done a disbursement.
default: default:
...@@ -650,10 +657,9 @@ func (d *Driver) logDatabaseContractMismatch( ...@@ -650,10 +657,9 @@ func (d *Driver) logDatabaseContractMismatch(
func (d *Driver) upsertDeposits(deposits []db.Deposit, end uint64) error { func (d *Driver) upsertDeposits(deposits []db.Deposit, end uint64) error {
err := d.cfg.Database.UpsertDeposits(deposits, end) err := d.cfg.Database.UpsertDeposits(deposits, end)
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodUpsertDeposits).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodUpsertDeposits).Inc()
return err return err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodUpsertDeposits).Set(0.0)
return nil return nil
} }
...@@ -662,59 +668,70 @@ func (d *Driver) confirmedDeposits(blockNumber uint64) ([]db.Deposit, error) { ...@@ -662,59 +668,70 @@ func (d *Driver) confirmedDeposits(blockNumber uint64) ([]db.Deposit, error) {
blockNumber, d.cfg.NumConfirmations, blockNumber, d.cfg.NumConfirmations,
) )
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodConfirmedDeposits).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodConfirmedDeposits).Inc()
return nil, err return nil, err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodConfirmedDeposits).Set(0.0)
return confirmedDeposits, nil return confirmedDeposits, nil
} }
func (d *Driver) lastProcessedBlock() (*uint64, error) { func (d *Driver) lastProcessedBlock() (*uint64, error) {
lastProcessedBlock, err := d.cfg.Database.LastProcessedBlock() lastProcessedBlock, err := d.cfg.Database.LastProcessedBlock()
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodLastProcessedBlock).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodLastProcessedBlock).Inc()
return nil, err return nil, err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodLastProcessedBlock).Set(0.0)
return lastProcessedBlock, nil return lastProcessedBlock, nil
} }
func (d *Driver) upsertPendingTx(pendingTx db.PendingTx) error { func (d *Driver) upsertPendingTx(pendingTx db.PendingTx) error {
err := d.cfg.Database.UpsertPendingTx(pendingTx) err := d.cfg.Database.UpsertPendingTx(pendingTx)
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodUpsertPendingTx).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodUpsertPendingTx).Inc()
return err return err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodUpsertPendingTx).Set(0.0)
return nil return nil
} }
func (d *Driver) listPendingTxs() ([]db.PendingTx, error) { func (d *Driver) listPendingTxs() ([]db.PendingTx, error) {
pendingTxs, err := d.cfg.Database.ListPendingTxs() pendingTxs, err := d.cfg.Database.ListPendingTxs()
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodListPendingTxs).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodListPendingTxs).Inc()
return nil, err return nil, err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodListPendingTxs).Set(0.0)
return pendingTxs, nil return pendingTxs, nil
} }
func (d *Driver) latestDisbursementID() (*uint64, error) { func (d *Driver) latestDisbursementID() (*uint64, error) {
lastDisbursementID, err := d.cfg.Database.LatestDisbursementID() lastDisbursementID, err := d.cfg.Database.LatestDisbursementID()
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodLatestDisbursementID).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodLatestDisbursementID).Inc()
return nil, err return nil, err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodLatestDisbursementID).Set(0.0)
return lastDisbursementID, nil return lastDisbursementID, nil
} }
func (d *Driver) deletePendingTx(startID, endID uint64) error { func (d *Driver) deletePendingTx(startID, endID uint64) error {
err := d.cfg.Database.DeletePendingTx(startID, endID) err := d.cfg.Database.DeletePendingTx(startID, endID)
if err != nil { if err != nil {
d.metrics.FailedDatabaseMethods.With(DBMethodDeletePendingTx).Set(1.0) d.metrics.FailedDatabaseMethods.With(DBMethodDeletePendingTx).Inc()
return err return err
} }
d.metrics.FailedDatabaseMethods.With(DBMethodDeletePendingTx).Set(0.0)
return nil return nil
} }
func (d *Driver) updateBalanceMetrics(ctx context.Context) {
disburserBal, err := d.cfg.L2Client.BalanceAt(ctx, d.walletAddr, nil)
if err != nil {
log.Error("Error getting disburser wallet balance", "err", err)
disburserBal = big.NewInt(0)
}
depositBal, err := d.cfg.L1Client.BalanceAt(ctx, d.cfg.DepositAddr, nil)
if err != nil {
log.Error("Error getting deposit contract balance", "err", err)
depositBal = big.NewInt(0)
}
d.metrics.DisburserBalance.Set(float64(disburserBal.Uint64()))
d.metrics.DepositContractBalance.Set(float64(depositBal.Uint64()))
}
...@@ -41,7 +41,7 @@ type Metrics struct { ...@@ -41,7 +41,7 @@ type Metrics struct {
// FailedDatabaseMethods tracks the number of database failures for each // FailedDatabaseMethods tracks the number of database failures for each
// known database method. // known database method.
FailedDatabaseMethods *prometheus.GaugeVec FailedDatabaseMethods *prometheus.CounterVec
// DepositIDMismatch tracks whether or not our database is in sync with the // DepositIDMismatch tracks whether or not our database is in sync with the
// disrburser contract. 1 means in sync, 0 means out of sync. // disrburser contract. 1 means in sync, 0 means out of sync.
...@@ -53,11 +53,11 @@ type Metrics struct { ...@@ -53,11 +53,11 @@ type Metrics struct {
// SuccessfulDisbursements tracks the number of disbursements that emit a // SuccessfulDisbursements tracks the number of disbursements that emit a
// success event from a given tx. // success event from a given tx.
SuccessfulDisbursements prometheus.Gauge SuccessfulDisbursements prometheus.Counter
// FailedDisbursements tracks the number of disbursements that emit a failed // FailedDisbursements tracks the number of disbursements that emit a failed
// event from a given tx. // event from a given tx.
FailedDisbursements prometheus.Gauge FailedDisbursements prometheus.Counter
// PostgresLastDisbursedID tracks the latest disbursement id in postgres. // PostgresLastDisbursedID tracks the latest disbursement id in postgres.
PostgresLastDisbursedID prometheus.Gauge PostgresLastDisbursedID prometheus.Gauge
...@@ -65,6 +65,12 @@ type Metrics struct { ...@@ -65,6 +65,12 @@ type Metrics struct {
// ContractNextDisbursementID tracks the next disbursement id expected by // ContractNextDisbursementID tracks the next disbursement id expected by
// the disburser contract. // the disburser contract.
ContractNextDisbursementID prometheus.Gauge ContractNextDisbursementID prometheus.Gauge
// DisburserBalance tracks Teleportr's disburser account balance.
DisburserBalance prometheus.Gauge
// DepositContractBalance tracks Teleportr's deposit contract balance.
DepositContractBalance prometheus.Gauge
} }
// NewMetrics initializes a new, extended metrics object. // NewMetrics initializes a new, extended metrics object.
...@@ -72,7 +78,7 @@ func NewMetrics(subsystem string) *Metrics { ...@@ -72,7 +78,7 @@ func NewMetrics(subsystem string) *Metrics {
base := metrics.NewBase(subsystem, "") base := metrics.NewBase(subsystem, "")
return &Metrics{ return &Metrics{
Base: base, Base: base,
FailedDatabaseMethods: promauto.NewGaugeVec(prometheus.GaugeOpts{ FailedDatabaseMethods: promauto.NewCounterVec(prometheus.CounterOpts{
Name: "failed_database_operations", Name: "failed_database_operations",
Help: "Tracks the number of database failures", Help: "Tracks the number of database failures",
Subsystem: base.SubsystemName(), Subsystem: base.SubsystemName(),
...@@ -111,5 +117,15 @@ func NewMetrics(subsystem string) *Metrics { ...@@ -111,5 +117,15 @@ func NewMetrics(subsystem string) *Metrics {
Help: "Next disbursement id expected by the disburser contract", Help: "Next disbursement id expected by the disburser contract",
Subsystem: base.SubsystemName(), Subsystem: base.SubsystemName(),
}), }),
DisburserBalance: promauto.NewGauge(prometheus.GaugeOpts{
Name: "disburser_balance",
Help: "Balance in Wei of Teleportr's disburser wallet",
Subsystem: base.SubsystemName(),
}),
DepositContractBalance: promauto.NewGauge(prometheus.GaugeOpts{
Name: "deposit_contract_balance",
Help: "Balance in Wei of Teleportr's deposit contract",
Subsystem: base.SubsystemName(),
}),
} }
} }
...@@ -24,74 +24,18 @@ var ( ...@@ -24,74 +24,18 @@ var (
Required: true, Required: true,
EnvVar: prefixAPIEnvVar("PORT"), EnvVar: prefixAPIEnvVar("PORT"),
} }
APIL1EthRpcFlag = cli.StringFlag{
Name: "l1-eth-rpc",
Usage: "The endpoint for the L1 ETH provider",
Required: true,
EnvVar: prefixAPIEnvVar("L1_ETH_RPC"),
}
APIDepositAddressFlag = cli.StringFlag{
Name: "deposit-address",
Usage: "Address of the TeleportrDeposit contract",
Required: true,
EnvVar: prefixAPIEnvVar("DEPOSIT_ADDRESS"),
}
APINumConfirmationsFlag = cli.StringFlag{
Name: "num-confirmations",
Usage: "Number of confirmations required until deposits are " +
"considered confirmed",
Required: true,
EnvVar: prefixAPIEnvVar("NUM_CONFIRMATIONS"),
}
APIPostgresHostFlag = cli.StringFlag{
Name: "postgres-host",
Usage: "Host of the teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_HOST"),
}
APIPostgresPortFlag = cli.Uint64Flag{
Name: "postgres-port",
Usage: "Port of the teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_PORT"),
}
APIPostgresUserFlag = cli.StringFlag{
Name: "postgres-user",
Usage: "Username of the teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_USER"),
}
APIPostgresPasswordFlag = cli.StringFlag{
Name: "postgres-password",
Usage: "Password of the teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_PASSWORD"),
}
APIPostgresDBNameFlag = cli.StringFlag{
Name: "postgres-db-name",
Usage: "Database name of the teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_DB_NAME"),
}
APIPostgresEnableSSLFlag = cli.BoolFlag{
Name: "postgres-enable-ssl",
Usage: "Whether or not to enable SSL on connections to " +
"teleportr postgres instance",
Required: true,
EnvVar: prefixAPIEnvVar("POSTGRES_ENABLE_SSL"),
}
) )
var APIFlags = []cli.Flag{ var APIFlags = []cli.Flag{
APIHostnameFlag, APIHostnameFlag,
APIPortFlag, APIPortFlag,
APIL1EthRpcFlag, L1EthRpcFlag,
APIDepositAddressFlag, DepositAddressFlag,
APINumConfirmationsFlag, NumDepositConfirmationsFlag,
APIPostgresHostFlag, PostgresHostFlag,
APIPostgresPortFlag, PostgresPortFlag,
APIPostgresUserFlag, PostgresUserFlag,
APIPostgresPasswordFlag, PostgresPasswordFlag,
APIPostgresDBNameFlag, PostgresDBNameFlag,
APIPostgresEnableSSLFlag, PostgresEnableSSLFlag,
} }
...@@ -126,16 +126,15 @@ var ( ...@@ -126,16 +126,15 @@ var (
Required: true, Required: true,
EnvVar: prefixEnvVar("POSTGRES_DB_NAME"), EnvVar: prefixEnvVar("POSTGRES_DB_NAME"),
} }
/* Optional Flags */
PostgresEnableSSLFlag = cli.BoolFlag{ PostgresEnableSSLFlag = cli.BoolFlag{
Name: "postgres-enable-ssl", Name: "postgres-enable-ssl",
Usage: "Whether or not to enable SSL on connections to " + Usage: "Whether or not to enable SSL on connections to " +
"teleportr postgres instance", "teleportr postgres instance",
Required: true, EnvVar: prefixEnvVar("POSTGRES_ENABLE_SSL"),
EnvVar: prefixEnvVar("POSTGRES_ENABLE_SSL"),
} }
/* Optional Flags */
LogLevelFlag = cli.StringFlag{ LogLevelFlag = cli.StringFlag{
Name: "log-level", Name: "log-level",
Usage: "The lowest log level that will be output", Usage: "The lowest log level that will be output",
...@@ -208,12 +207,12 @@ var requiredFlags = []cli.Flag{ ...@@ -208,12 +207,12 @@ var requiredFlags = []cli.Flag{
PostgresUserFlag, PostgresUserFlag,
PostgresPasswordFlag, PostgresPasswordFlag,
PostgresDBNameFlag, PostgresDBNameFlag,
PostgresEnableSSLFlag,
} }
var optionalFlags = []cli.Flag{ var optionalFlags = []cli.Flag{
LogLevelFlag, LogLevelFlag,
LogTerminalFlag, LogTerminalFlag,
PostgresEnableSSLFlag,
DisburserPrivateKeyFlag, DisburserPrivateKeyFlag,
MnemonicFlag, MnemonicFlag,
DisburserHDPathFlag, DisburserHDPathFlag,
......
...@@ -85,7 +85,7 @@ func Main(gitVersion string) func(ctx *cli.Context) error { ...@@ -85,7 +85,7 @@ func Main(gitVersion string) func(ctx *cli.Context) error {
go metrics.RunServer(cfg.MetricsHostname, cfg.MetricsPort) go metrics.RunServer(cfg.MetricsHostname, cfg.MetricsPort)
} }
chainID, err := l1Client.ChainID(ctx) chainID, err := l2Client.ChainID(ctx)
if err != nil { if err != nil {
return err return err
} }
...@@ -120,7 +120,7 @@ func Main(gitVersion string) func(ctx *cli.Context) error { ...@@ -120,7 +120,7 @@ func Main(gitVersion string) func(ctx *cli.Context) error {
Driver: teleportrDriver, Driver: teleportrDriver,
PollInterval: cfg.PollInterval, PollInterval: cfg.PollInterval,
ClearPendingTx: false, ClearPendingTx: false,
L1Client: l1Client, L1Client: l2Client,
TxManagerConfig: txManagerConfig, TxManagerConfig: txManagerConfig,
}) })
...@@ -152,3 +152,33 @@ func Main(gitVersion string) func(ctx *cli.Context) error { ...@@ -152,3 +152,33 @@ func Main(gitVersion string) func(ctx *cli.Context) error {
return nil return nil
} }
} }
func Migrate() func(ctx *cli.Context) error {
return func(cliCtx *cli.Context) error {
cfg, err := NewConfig(cliCtx)
if err != nil {
return err
}
log.Info("Initializing teleportr")
database, err := db.Open(db.Config{
Host: cfg.PostgresHost,
Port: uint16(cfg.PostgresPort),
User: cfg.PostgresUser,
Password: cfg.PostgresPassword,
DBName: cfg.PostgresDBName,
EnableSSL: cfg.PostgresEnableSSL,
})
if err != nil {
return err
}
log.Info("Migrating database")
if err := database.Migrate(); err != nil {
return err
}
log.Info("Done")
return nil
}
}
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kovan-replica-0-5-14
commonLabels:
network: kovan
provider: internal
bases:
- ../../envs/kovan-gen5-berlin
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/configmaps
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.3
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
- path: ./patches/dtl-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: data-transport-layer
persistentVolumeClaim:
claimName: data-transport-layer-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
value: http://failover-proxyd.default:8080
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
value: http://sequencer.default:8545
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
\ No newline at end of file
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
env:
- name: IPC_DISABLE
value: "false"
resources:
limits:
cpu: "4"
memory: 12Gi
requests:
cpu: "2"
memory: 8Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: replica-healthcheck
spec:
template:
spec:
containers:
- name: replica-healthcheck
env:
- name: REPLICA_HEALTHCHECK__ETH_NETWORK_RPC_PROVIDER
value: http://sequencer.default:8545
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
\ No newline at end of file
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mainnet-replica-0-5-14
commonLabels:
network: mainnet
provider: internal
bases:
- ../../../envs/mainnet-gen5-berlin
- ../../../scripts
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
- path: ./patches/dtl-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: data-transport-layer
persistentVolumeClaim:
claimName: data-transport-layer-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
value: http://failover-proxyd.default:8080
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
value: http://sequencer.default:8545
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
env:
- name: IPC_DISABLE
value: "false"
resources:
limits:
cpu: "4"
memory: 12Gi
requests:
cpu: "2"
memory: 8Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: replica-healthcheck
spec:
template:
spec:
containers:
- name: replica-healthcheck
env:
- name: REPLICA_HEALTHCHECK__ETH_NETWORK_RPC_PROVIDER
value: http://sequencer.default:8545
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mainnet-replica-l1-0-5-14
commonLabels:
network: mainnet
provider: internal
sync_source: l1
bases:
- ../../../envs/mainnet-gen5-l1-berlin/
- ../../../scripts
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
- path: ./patches/dtl-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: data-transport-layer
persistentVolumeClaim:
claimName: data-transport-layer-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
value: http://failover-proxyd.default:8080
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
value: http://sequencer.default:8545
- name: L1_NODE_WEB3_URL
value: http://failover-proxyd.default:8080
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
env:
- name: IPC_DISABLE
value: "false"
resources:
limits:
cpu: "4"
memory: 12Gi
requests:
cpu: "2"
memory: 8Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: replica-healthcheck
spec:
replicas: 1
template:
spec:
containers:
- name: replica-healthcheck
env:
- name: REPLICA_HEALTHCHECK__ETH_NETWORK_RPC_PROVIDER
value: http://sequencer.default:8545
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kovan-replica-0-5-14
annotations:
kubernetes.io/ingress.class: gce
kubernetes.io/ingress.global-static-ip-name: kovan-replica-0-5-14
networking.gke.io/managed-certificates: kovan-replica-0-5-14
spec:
rules:
- host: kovan-replica-0-5-14.optimism.io
http:
paths:
- backend:
service:
name: l2geth-replica
port:
name: rpc
path: /
pathType: ImplementationSpecific
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: kovan-replica-0-5-14
spec:
domains:
- kovan-replica-0-5-14.optimism.io
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kovan-replica-0-5-14
commonLabels:
network: kovan
provider: internal
bases:
- ../../../envs/kovan-gen5-berlin
- ../../../scripts
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ./ingress.yaml
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
- path: ./patches/dtl-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: data-transport-layer
persistentVolumeClaim:
claimName: data-transport-layer-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l2-rpc-endpoint
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
\ No newline at end of file
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
env:
- name: IPC_DISABLE
value: "false"
resources:
limits:
cpu: "4"
memory: 12Gi
requests:
cpu: "2"
memory: 8Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: replica-healthcheck
spec:
template:
spec:
containers:
- name: replica-healthcheck
env:
- name: REPLICA_HEALTHCHECK__ETH_NETWORK_RPC_PROVIDER
value: https://kovan.optimism.io
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mainnet-replica-0-5-14
annotations:
kubernetes.io/ingress.class: gce
kubernetes.io/ingress.global-static-ip-name: mainnet-replica-0-5-14
networking.gke.io/managed-certificates: mainnet-replica-0-5-14
spec:
rules:
- host: mainnet-replica-0-5-14.optimism.io
http:
paths:
- backend:
service:
name: l2geth-replica
port:
name: rpc
path: /
pathType: ImplementationSpecific
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: mainnet-replica-0-5-14
spec:
domains:
- mainnet-replica-0-5-14.optimism.io
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mainnet-replica-0-5-14
commonLabels:
network: mainnet
provider: internal
bases:
- ../../../envs/mainnet-gen5-berlin/
- ../../../scripts
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ./volumes.yaml
- ./ingress.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.3
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
\ No newline at end of file
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l2-rpc-endpoint
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
\ No newline at end of file
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
command:
- geth
- --config=/l2geth-config/l2geth.toml
- --datadir=$(DATADIR)
- --password=$(DATADIR)/password
- --allow-insecure-unlock
- --unlock=$(BLOCK_SIGNER_ADDRESS)
- --mine
- --miner.etherbase=$(BLOCK_SIGNER_ADDRESS)
- --metrics
- --metrics.influxdb
- --metrics.influxdb.endpoint=http://influxdb.monitoring:8086
- --metrics.influxdb.database=$(NAMESPACE)
resources:
limits:
cpu: "8"
memory: 24Gi
requests:
cpu: "4"
memory: 12Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l2-rpc-endpoint
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: replica-healthcheck
spec:
template:
spec:
containers:
- name: replica-healthcheck
env:
- name: REPLICA_HEALTHCHECK__ETH_NETWORK_RPC_PROVIDER
value: https://mainnet.optimism.io
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
\ No newline at end of file
...@@ -10,8 +10,9 @@ OVMCONTEXT_SPEC_NUM_TXS=1 ...@@ -10,8 +10,9 @@ OVMCONTEXT_SPEC_NUM_TXS=1
RUN_WITHDRAWAL_TESTS=false RUN_WITHDRAWAL_TESTS=false
RUN_DEBUG_TRACE_TESTS=false RUN_DEBUG_TRACE_TESTS=false
RUN_REPLICA_TESTS=false RUN_REPLICA_TESTS=false
RUN_HEALTHCHECK_TESTS=false
RUN_STRESS_TESTS=false RUN_STRESS_TESTS=false
# Can be configured up or down as necessary # Can be configured up or down as necessary
MOCHA_TIMEOUT=300000 MOCHA_TIMEOUT=300000
# Set to true to make Mocha stop after the first failed test. # Set to true to make Mocha stop after the first failed test.
MOCHA_BAIL=false MOCHA_BAIL=false
\ No newline at end of file
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
"hardhat-gas-reporter": "^1.0.4", "hardhat-gas-reporter": "^1.0.4",
"lint-staged": "11.0.0", "lint-staged": "11.0.0",
"mocha": "^8.4.0", "mocha": "^8.4.0",
"node-fetch": "^2.6.7",
"prom-client": "^14.0.1", "prom-client": "^14.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"typescript": "^4.3.5", "typescript": "^4.3.5",
......
import fetch from 'node-fetch'
import { expect } from './shared/setup'
import { envConfig } from './shared/utils'
describe('Healthcheck Tests', () => {
before(async function () {
if (!envConfig.RUN_HEALTHCHECK_TESTS) {
this.skip()
}
})
// Super simple test, is the metric server up?
it('should have metrics exposed', async () => {
const response = await fetch(envConfig.HEALTHCHECK_URL)
expect(response.status).to.equal(200)
})
})
...@@ -56,6 +56,8 @@ const procEnv = cleanEnv(process.env, { ...@@ -56,6 +56,8 @@ const procEnv = cleanEnv(process.env, {
VERIFIER_URL: str({ default: 'http://localhost:8547' }), VERIFIER_URL: str({ default: 'http://localhost:8547' }),
HEALTHCHECK_URL: str({ default: 'http://localhost:7300/metrics' }),
PRIVATE_KEY: str({ PRIVATE_KEY: str({
default: default:
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
...@@ -78,6 +80,9 @@ const procEnv = cleanEnv(process.env, { ...@@ -78,6 +80,9 @@ const procEnv = cleanEnv(process.env, {
RUN_REPLICA_TESTS: bool({ RUN_REPLICA_TESTS: bool({
default: true, default: true,
}), }),
RUN_HEALTHCHECK_TESTS: bool({
default: true,
}),
RUN_DEBUG_TRACE_TESTS: bool({ RUN_DEBUG_TRACE_TESTS: bool({
default: true, default: true,
}), }),
......
...@@ -36,30 +36,7 @@ services: ...@@ -36,30 +36,7 @@ services:
# Env vars for the deployment script. # Env vars for the deployment script.
CONTRACTS_RPC_URL: http://l1_chain:8545 CONTRACTS_RPC_URL: http://l1_chain:8545
CONTRACTS_DEPLOYER_KEY: 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' CONTRACTS_DEPLOYER_KEY: 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
CONTRACTS_TARGET_NETWORK: 'custom' CONTRACTS_TARGET_NETWORK: 'local'
OVM_ADDRESS_MANAGER_OWNER: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
OVM_PROPOSER_ADDRESS: '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc'
OVM_SEQUENCER_ADDRESS: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
SCC_FRAUD_PROOF_WINDOW: 0
NUM_DEPLOY_CONFIRMATIONS: 0
# skip compilation when run in docker-compose, since the contracts
# were already compiled in the builder step
NO_COMPILE: 1
# Env vars for the dump script.
# Default hardhat account 5
GAS_PRICE_ORACLE_OWNER: '0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc'
# setting the whitelist owner to address(0) disables the whitelist
WHITELIST_OWNER: '0x0000000000000000000000000000000000000000'
L1_FEE_WALLET_ADDRESS: '0x391716d440c151c42cdf1c95c1d83a5427bca52c'
L2_CHAIN_ID: 987
L2_BLOCK_GAS_LIMIT: 15000000
BLOCK_SIGNER_ADDRESS: '0x00000398232E2064F896018496b4b44b3D62751F'
GAS_PRICE_ORACLE_OVERHEAD: 2750
GAS_PRICE_ORACLE_SCALAR: 1500000
GAS_PRICE_ORACLE_L1_BASE_FEE: 1
GAS_PRICE_ORACLE_GAS_PRICE: 1
GAS_PRICE_ORACLE_DECIMALS: 6
ports: ports:
# expose the service to the host for getting the contract addrs # expose the service to the host for getting the contract addrs
- ${DEPLOYER_PORT:-8080}:8081 - ${DEPLOYER_PORT:-8080}:8081
...@@ -197,6 +174,23 @@ services: ...@@ -197,6 +174,23 @@ services:
- ${REPLICA_HTTP_PORT:-8549}:8545 - ${REPLICA_HTTP_PORT:-8549}:8545
- ${REPLICA_WS_PORT:-8550}:8546 - ${REPLICA_WS_PORT:-8550}:8546
replica-healthcheck:
depends_on:
- l2geth
- replica
deploy:
replicas: 0
build:
context: ..
dockerfile: ./ops/docker/Dockerfile.packages
target: replica-healthcheck
image: ethereumoptimism/replica-healthcheck:${DOCKER_TAG_REPLICA_HEALTHCHECK:-latest}
environment:
HEALTHCHECK__REFERENCE_RPC_PROVIDER: http://l2geth:8545
HEALTHCHECK__TARGET_RPC_PROVIDER: http://replica:8545
ports:
- ${HEALTHCHECK_HTTP_PORT:-7300}:7300
integration_tests: integration_tests:
deploy: deploy:
replicas: 0 replicas: 0
...@@ -209,6 +203,7 @@ services: ...@@ -209,6 +203,7 @@ services:
environment: environment:
L1_URL: http://l1_chain:8545 L1_URL: http://l1_chain:8545
L2_URL: http://l2geth:8545 L2_URL: http://l2geth:8545
HEALTHCHECK_URL: http://replica-healthcheck:7300/metrics
REPLICA_URL: http://replica:8545 REPLICA_URL: http://replica:8545
VERIFIER_URL: http://verifier:8545 VERIFIER_URL: http://verifier:8545
URL: http://deployer:8081/addresses.json URL: http://deployer:8081/addresses.json
......
...@@ -61,5 +61,5 @@ CMD ["npm", "run", "start"] ...@@ -61,5 +61,5 @@ CMD ["npm", "run", "start"]
FROM base as replica-healthcheck FROM base as replica-healthcheck
WORKDIR /opts/optimism/packages/replica-healthcheck WORKDIR /opt/optimism/packages/replica-healthcheck
ENTRYPOINT ["npm", "run", "start"] ENTRYPOINT ["npm", "run", "start"]
FROM golang:1.17.3-alpine3.13 as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
COPY ./go/bss-core /go/bss-core
COPY ./go/teleportr/go.mod ./go/teleportr/go.sum /go/teleportr/
WORKDIR /go/teleportr
RUN go mod graph | grep -v bss-core | awk '{if ($1 !~ "@") print $2}' | xargs -n 1 go get
COPY ./go/teleportr/ ./
RUN make teleportr teleportr-api
FROM alpine:3.13
RUN apk add --no-cache ca-certificates jq curl
COPY --from=builder /go/teleportr/teleportr /usr/local/bin/
COPY --from=builder /go/teleportr/teleportr-api /usr/local/bin/
CMD ["teleportr"]
FROM golang:1.17.8-alpine3.15
RUN apk add --no-cache make gcc musl-dev linux-headers git jq curl bash gzip ca-certificates openssh && \
go install gotest.tools/gotestsum@latest && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.44.2
CMD ["bash"]
FROM python:3.8.12-slim-buster
RUN apt-get update && \
apt-get install -y curl openssh-client git build-essential ca-certificates && \
curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \
bash nodesource_setup.sh && \
apt-get install -y nodejs && \
npm i -g yarn && \
npm i -g depcheck && \
pip install slither-analyzer
...@@ -24,39 +24,7 @@ curl \ ...@@ -24,39 +24,7 @@ curl \
echo "Connected to L1." echo "Connected to L1."
echo "Building deployment command." echo "Building deployment command."
DEPLOY_CMD="npx hardhat deploy" DEPLOY_CMD="npx hardhat deploy --network $CONTRACTS_TARGET_NETWORK"
# Helper method to concatenate things onto $DEPLOY_CMD.
# Usage: concat_cmd "str-to-concat"
function concat_cmd() {
DEPLOY_CMD="$DEPLOY_CMD $1"
}
# Helper method to conditionally concatenate CLI arguments
# when a given env var is defined.
# Usage: concat_arg "--arg-name" "env-var-name"
function concat_arg() {
ARG=$1
ENV_VAR=$2
if [ -n "${!ENV_VAR+x}" ]; then
echo "$ENV_VAR set to ${!ENV_VAR}, applying $ARG argument."
concat_cmd "$ARG \"${!ENV_VAR}\""
else
echo "$ENV_VAR is not not set, skipping $ARG argument."
fi
}
concat_arg "--network" "CONTRACTS_TARGET_NETWORK"
concat_arg "--ovm-address-manager-owner" "OVM_ADDRESS_MANAGER_OWNER"
concat_arg "--ovm-proposer-address" "OVM_PROPOSER_ADDRESS"
concat_arg "--ovm-sequencer-address" "OVM_SEQUENCER_ADDRESS"
concat_arg "--l1-block-time-seconds" "L1_BLOCK_TIME_SECONDS"
concat_arg "--ctc-max-transaction-gas-limit" "CTC_MAX_TRANSACTION_GAS_LIMIT"
concat_arg "--ctc-l2-gas-discount-divisor" "CTC_L2_GAS_DISCOUNT_DIVISOR"
concat_arg "--ctc-enqueue-gas-cost" "CTC_ENQUEUE_GAS_COST"
concat_arg "--scc-fraud-proof-window" "SCC_FRAUD_PROOF_WINDOW"
concat_arg "--num-deploy-confirmations" "NUM_DEPLOY_CONFIRMATIONS"
concat_arg "--forked" "FORKED"
echo "Deploying contracts. Deployment command:" echo "Deploying contracts. Deployment command:"
echo "$DEPLOY_CMD" echo "$DEPLOY_CMD"
...@@ -81,20 +49,13 @@ echo "}" >> addresses.json ...@@ -81,20 +49,13 @@ echo "}" >> addresses.json
echo "Built addresses.json. Content:" echo "Built addresses.json. Content:"
jq . addresses.json jq . addresses.json
echo "Env vars for the dump script:"
export L1_STANDARD_BRIDGE_ADDRESS=$(cat "./addresses.json" | jq -r .Proxy__OVM_L1StandardBridge)
export L1_CROSS_DOMAIN_MESSENGER_ADDRESS=$(cat "./addresses.json" | jq -r .Proxy__OVM_L1CrossDomainMessenger)
echo "ADDRESS_MANAGER_ADDRESS=$ADDRESS_MANAGER_ADDRESS"
echo "L1_STANDARD_BRIDGE_ADDRESS=$L1_STANDARD_BRIDGE_ADDRESS"
echo "L1_CROSS_DOMAIN_MESSENGER_ADDRESS=$L1_CROSS_DOMAIN_MESSENGER_ADDRESS"
echo "Building dump file." echo "Building dump file."
yarn run build:dump npx hardhat take-dump --network $CONTRACTS_TARGET_NETWORK
mv addresses.json ./dist/dumps mv addresses.json ./genesis
cp ./genesis/$CONTRACTS_TARGET_NETWORK.json ./genesis/state-dump.latest.json
# service the addresses and dumps # service the addresses and dumps
echo "Starting server." echo "Starting server."
python3 -m http.server \ python3 -m http.server \
--bind "0.0.0.0" 8081 \ --bind "0.0.0.0" 8081 \
--directory ./dist/dumps --directory ./genesis
...@@ -23,4 +23,4 @@ curl \ ...@@ -23,4 +23,4 @@ curl \
--output /dev/null \ --output /dev/null \
$L2_URL $L2_URL
npx hardhat test --network optimism --no-compile npx hardhat test --network optimism --no-compile "$@"
#!/bin/bash #!/bin/bash
CONTAINER=l2geth CONTAINER=l2geth
RETRIES=30 RETRIES=90
i=0 i=0
until docker-compose logs l2geth | grep -q "Starting Sequencer Loop"; until docker-compose logs l2geth | grep -q "Starting Sequencer Loop";
do do
sleep 3 sleep 1
if [ $i -eq $RETRIES ]; then if [ $i -eq $RETRIES ]; then
echo 'Timed out waiting for sequencer' echo 'Timed out waiting for sequencer'
break break
......
/* Imports: External */ import { Server } from 'net'
import Config from 'bcfg' import Config from 'bcfg'
import * as dotenv from 'dotenv' import * as dotenv from 'dotenv'
import { Command, Option } from 'commander' import { Command, Option } from 'commander'
import { ValidatorSpec, Spec, cleanEnv } from 'envalid' import { ValidatorSpec, Spec, cleanEnv } from 'envalid'
import { sleep } from '@eth-optimism/core-utils' import { sleep } from '@eth-optimism/core-utils'
import snakeCase from 'lodash/snakeCase' import snakeCase from 'lodash/snakeCase'
import express from 'express'
import prometheus, { Registry } from 'prom-client'
/* Imports: Internal */
import { Logger } from '../common/logger' import { Logger } from '../common/logger'
import { Metric } from './metrics' import { Metric } from './metrics'
...@@ -82,6 +84,26 @@ export abstract class BaseServiceV2< ...@@ -82,6 +84,26 @@ export abstract class BaseServiceV2<
*/ */
protected readonly metrics: TMetrics protected readonly metrics: TMetrics
/**
* Registry for prometheus metrics.
*/
protected readonly metricsRegistry: Registry
/**
* Metrics server.
*/
protected metricsServer: Server
/**
* Port for the metrics server.
*/
protected readonly metricsServerPort: number
/**
* Hostname for the metrics server.
*/
protected readonly metricsServerHostname: string
/** /**
* @param params Options for the construction of the service. * @param params Options for the construction of the service.
* @param params.name Name for the service. This name will determine the prefix used for logging, * @param params.name Name for the service. This name will determine the prefix used for logging,
...@@ -93,6 +115,8 @@ export abstract class BaseServiceV2< ...@@ -93,6 +115,8 @@ export abstract class BaseServiceV2<
* @param params.options Options to pass to the service. * @param params.options Options to pass to the service.
* @param params.loops Whether or not the service should loop. Defaults to true. * @param params.loops Whether or not the service should loop. Defaults to true.
* @param params.loopIntervalMs Loop interval in milliseconds. Defaults to zero. * @param params.loopIntervalMs Loop interval in milliseconds. Defaults to zero.
* @param params.metricsServerPort Port for the metrics server. Defaults to 7300.
* @param params.metricsServerHostname Hostname for the metrics server. Defaults to 0.0.0.0.
*/ */
constructor(params: { constructor(params: {
name: string name: string
...@@ -101,6 +125,8 @@ export abstract class BaseServiceV2< ...@@ -101,6 +125,8 @@ export abstract class BaseServiceV2<
options?: Partial<TOptions> options?: Partial<TOptions>
loop?: boolean loop?: boolean
loopIntervalMs?: number loopIntervalMs?: number
metricsServerPort?: number
metricsServerHostname?: string
}) { }) {
this.loop = params.loop !== undefined ? params.loop : true this.loop = params.loop !== undefined ? params.loop : true
this.loopIntervalMs = this.loopIntervalMs =
...@@ -203,6 +229,11 @@ export abstract class BaseServiceV2< ...@@ -203,6 +229,11 @@ export abstract class BaseServiceV2<
return acc return acc
}, {}) as TMetrics }, {}) as TMetrics
// Create the metrics server.
this.metricsRegistry = prometheus.register
this.metricsServerPort = params.metricsServerPort || 7300
this.metricsServerHostname = params.metricsServerHostname || '0.0.0.0'
this.logger = new Logger({ name: params.name }) this.logger = new Logger({ name: params.name })
// Gracefully handle stop signals. // Gracefully handle stop signals.
...@@ -222,6 +253,33 @@ export abstract class BaseServiceV2< ...@@ -222,6 +253,33 @@ export abstract class BaseServiceV2<
public async run(): Promise<void> { public async run(): Promise<void> {
this.done = false this.done = false
// Start the metrics server if not yet running.
if (!this.metricsServer) {
this.logger.info('starting metrics server')
await new Promise((resolve) => {
const app = express()
app.get('/metrics', async (_, res) => {
res.status(200).send(await this.metricsRegistry.metrics())
})
this.metricsServer = app.listen(
this.metricsServerPort,
this.metricsServerHostname,
() => {
resolve(null)
}
)
})
this.logger.info(`metrics started`, {
port: this.metricsServerPort,
hostname: this.metricsServerHostname,
route: '/metrics',
})
}
if (this.init) { if (this.init) {
this.logger.info('initializing service') this.logger.info('initializing service')
await this.init() await this.init()
...@@ -267,7 +325,18 @@ export abstract class BaseServiceV2< ...@@ -267,7 +325,18 @@ export abstract class BaseServiceV2<
while (!this.done) { while (!this.done) {
await sleep(1000) await sleep(1000)
} }
this.logger.info('main loop finished, goodbye!')
// Shut down the metrics server if it's running.
if (this.metricsServer) {
this.logger.info('stopping metrics server')
await new Promise((resolve) => {
this.metricsServer.close(() => {
resolve(null)
})
})
this.logger.info('metrics server stopped')
this.metricsServer = undefined
}
} }
/** /**
......
# Name for the network to deploy to ("mainnet", "kovan", etc.)
CONTRACTS_TARGET_NETWORK=
# Private key that will send deployment transactions
CONTRACTS_DEPLOYER_KEY=
# RPC URL connected to the L1 chain we're deploying to
CONTRACTS_RPC_URL=
# Your Etherscan API key for the L1 network
ETHERSCAN_API_KEY=
module.exports = { module.exports = {
extends: '../../.eslintrc.js', extends: '../../.eslintrc.js',
ignorePatterns: [
'src/contract-artifacts.ts',
'src/contract-deployed-artifacts.ts',
],
} }
...@@ -32,7 +32,9 @@ import { L1CrossDomainMessenger } from "@eth-optimism/contracts/L1/messaging/L1C ...@@ -32,7 +32,9 @@ import { L1CrossDomainMessenger } from "@eth-optimism/contracts/L1/messaging/L1C
``` ```
## Guide for Developers ## Guide for Developers
### Setup ### Setup
Install the following: Install the following:
- [`Node.js` (14+)](https://nodejs.org/en/) - [`Node.js` (14+)](https://nodejs.org/en/)
- [`npm`](https://www.npmjs.com/get-npm) - [`npm`](https://www.npmjs.com/get-npm)
...@@ -46,87 +48,75 @@ cd contracts ...@@ -46,87 +48,75 @@ cd contracts
``` ```
Install `npm` packages: Install `npm` packages:
```shell ```shell
yarn install yarn install
``` ```
### Running Tests ### Running Tests
Tests are executed via `yarn`: Tests are executed via `yarn`:
```shell ```shell
yarn test yarn test
``` ```
Run specific tests by giving a path to the file you want to run: Run specific tests by giving a path to the file you want to run:
```shell ```shell
yarn test ./test/path/to/my/test.spec.ts yarn test ./test/path/to/my/test.spec.ts
``` ```
### Measuring test coverage: ### Measuring test coverage:
```shell ```shell
yarn test:coverage yarn test:coverage
``` ```
The output is most easily viewable by opening the html file in your browser: The output is most easily viewable by opening the html file in your browser:
```shell ```shell
open ./coverage/index.html open ./coverage/index.html
``` ```
### Compiling and Building ### Compiling and Building
Easiest way is to run the primary build script:
```shell
yarn build
```
Running the full build command will perform the following actions: Compile and build the various required with the `build` command:
1. `build:contracts` - Compile all Solidity contracts with both the EVM and OVM compilers.
2. `build:typescript` - Builds the typescript files that are used to export utilities into js.
3. `build:copy` - Copies various other files into the dist folder.
4. `build:dump` - Generates a genesis state from the contracts that L2 geth will use.
5. `build:typechain` - Generates [TypeChain](https://github.com/ethereum-ts/TypeChain) artifacts.
You can also build specific components as follows:
```shell ```shell
yarn build:contracts yarn build
``` ```
### Deploying the Contracts ### Deploying the Contracts
#### Required environment variables #### Required environment variables
You must set the following environment variables to execute a deployment: You must set several required environment variables before you can execute a deployment.
Duplicate the file [`.env.example`](./.env.example) and rename your duplicate to `.env`.
```bash Fill out each of the environment variables before continuing.
# Name for the network to deploy to ("mainnet", "kovan", etc.)
export CONTRACTS_TARGET_NETWORK=...
# Private key that will send deployment transactions
export CONTRACTS_DEPLOYER_KEY=...
# RPC URL connected to the L1 chain we're deploying to #### Creating a deployment configuration
export CONTRACTS_RPC_URL=...
# Your Etherscan API key for the L1 network Before you can carry out a deployment, you must create a deployment configuration file inside of the [deploy-config](./deploy-config/) folder.
export ETHERSCAN_API_KEY=... Deployment configuration files are TypeScript files that export an object that conforms to the `DeployConfig` type.
``` See [mainnet.ts](./deploy-config/mainnet.ts) for an example deployment configuration.
We recommend duplicating an existing deployment config and modifying it to satisfy your requirements.
#### Creating a deployment script
Before you can carry out a deployment, you must create a deployment script. #### Executing a deployment
See [mainnet.sh](./scripts/deploy-scripts/mainnet.sh) for an example deployment script.
We recommend duplicating an existing deployment script and modifying it to satisfy your requirements.
Most variables within the deploy script are relatively self-explanatory. Once you've created your deploy config, you can execute a deployment with the following command:
If you intend to upgrade an existing system you **MUST** [include the following argument](https://github.com/ethereum-optimism/optimism/blob/6f633f915b34a46ac14430724bed9722af8bd05e/packages/contracts/scripts/deploy-scripts/mainnet.sh#L33) in the deploy script:
``` ```
--tags upgrade npx hardhat deploy --network <my network name>
``` ```
If you are deploying a system from scratch, you should **NOT** include `--tags upgrade` or you will fail to deploy several contracts. Note that this only applies to fresh deployments.
If you want to upgrade an existing system (instead of deploying a new system from scratch), you must use the following command instead:
#### Executing a deployment ```
npx hardhat deploy --network <my network name> --tags upgrade
```
Once you've created your deploy script, simply run the script to trigger a deployment.
During the deployment process, you will be asked to transfer ownership of several contracts to a special contract address. During the deployment process, you will be asked to transfer ownership of several contracts to a special contract address.
You will also be asked to verify various configuration values. You will also be asked to verify various configuration values.
This is a safety mechanism to make sure that actions within an upgrade are performed atomically. This is a safety mechanism to make sure that actions within an upgrade are performed atomically.
...@@ -134,19 +124,29 @@ Ownership of these addresses will be automatically returned to the original owne ...@@ -134,19 +124,29 @@ Ownership of these addresses will be automatically returned to the original owne
The original owner can always recover ownership from the upgrade contract in an emergency. The original owner can always recover ownership from the upgrade contract in an emergency.
Please read these instructions carefully, verify each of the presented configuration values, and carefully confirm that the contract you are giving ownership to has not been compromised (e.g., check the code on Etherscan). Please read these instructions carefully, verify each of the presented configuration values, and carefully confirm that the contract you are giving ownership to has not been compromised (e.g., check the code on Etherscan).
After your deployment is complete, your new contracts will be written to an artifacts directory in `./deployments/<name>`. After your deployment is complete, your new contracts will be written to an artifacts directory in `./deployments/<my network name>`.
Your contracts will also be automatically verified as part of the deployment script.
#### Verifying contract source code
Contracts will be automatically verified via both [Etherscan](https://etherscan.io) and [Sourcify](https://sourcify.dev/) during the deployment process.
If there was an issue with verification during the deployment, you can manually verify your contracts with the command:
```
npx hardhat etherscan-verify --network <my network name>
```
#### Creating a genesis file #### Creating a genesis file
Optimism expects that certain contracts (called "predeploys") be deployed to the L2 network at pre-determined addresses. Optimism expects that certain contracts (called "predeploys") be deployed to the L2 network at pre-determined addresses.
Doing this requires that you generate a special genesis file to be used by your corresponding L2Geth nodes. We guarantee this by creating a genesis file in which certain contracts are already within the L2 state at the genesis block.
You must first create a genesis generation script. To create the genesis file for your network, you must first deploy the L1 contracts using the appropriate commands from above.
Like in the deploy script, we recommend starting from an [existing script](./scripts/deploy-scripts/mainnet-genesis.sh). Once you've deployed your contracts, run the following command:
Modify each of the values within this script to match the values of your own deployment, taking any L1 contract addresses from the `./deployments/<name>` folder that was just generated or modified.
```
npx hardhat take-dump --network <my network name>
```
Execute this script to generate the genesis file. A genesis file will be created for you at `/genesis/<my network name>.json`.
You will find this genesis file at `./dist/dumps/state-dump.latest.json`.
You can then ingest this file via `geth init`. You can then ingest this file via `geth init`.
### Hardhat tasks ### Hardhat tasks
......
/* External Imports */
import * as fs from 'fs'
import * as path from 'path'
import * as mkdirp from 'mkdirp'
const ensure = (value, key) => {
if (typeof value === 'undefined' || value === null || Number.isNaN(value)) {
throw new Error(`${key} is undefined, null or NaN`)
}
}
/* Internal Imports */
import { makeL2GenesisFile } from '../src/make-genesis'
;(async () => {
const outdir = path.resolve(__dirname, '../dist/dumps')
const outfile = path.join(outdir, 'state-dump.latest.json')
mkdirp.sync(outdir)
const env = process.env
// An account that represents the owner of the whitelist
const whitelistOwner = env.WHITELIST_OWNER
// The gas price oracle owner, can update values is GasPriceOracle L2 predeploy
const gasPriceOracleOwner = env.GAS_PRICE_ORACLE_OWNER
// The initial overhead value for the GasPriceOracle
const gasPriceOracleOverhead = parseInt(
env.GAS_PRICE_ORACLE_OVERHEAD || '2750',
10
)
// The initial scalar value for the GasPriceOracle. The actual
// scalar is scaled downwards by the number of decimals
const gasPriceOracleScalar = parseInt(
env.GAS_PRICE_ORACLE_SCALAR || '1500000',
10
)
// The initial decimals that scale down the scalar in the GasPriceOracle
const gasPriceOracleDecimals = parseInt(
env.GAS_PRICE_ORACLE_DECIMALS || '6',
10
)
// The initial L1 base fee in the GasPriceOracle. This determines how
// expensive the L1 portion of the transaction fee is.
const gasPriceOracleL1BaseFee = parseInt(
env.GAS_PRICE_ORACLE_L1_BASE_FEE || '1',
10
)
// The initial L2 gas price set in the GasPriceOracle
const gasPriceOracleGasPrice = parseInt(
env.GAS_PRICE_ORACLE_GAS_PRICE || '1',
10
)
// The L2 block gas limit, used in the L2 block headers as well to limit
// the amount of execution for a single block.
const l2BlockGasLimit = parseInt(env.L2_BLOCK_GAS_LIMIT, 10)
// The L2 chain id, added to the chain config
const l2ChainId = parseInt(env.L2_CHAIN_ID, 10)
// The block signer address, added to the block extradata for clique consensus
const blockSignerAddress = env.BLOCK_SIGNER_ADDRESS
// The L1 standard bridge address for cross domain messaging
const l1StandardBridgeAddress = env.L1_STANDARD_BRIDGE_ADDRESS
// The L1 fee wallet address, used to restrict the account that fees on L2 can
// be withdrawn to on L1
const l1FeeWalletAddress = env.L1_FEE_WALLET_ADDRESS
// The L1 cross domain messenger address, used for cross domain messaging
const l1CrossDomainMessengerAddress = env.L1_CROSS_DOMAIN_MESSENGER_ADDRESS
// The block height at which the berlin hardfork activates
const berlinBlock = parseInt(env.BERLIN_BLOCK, 10) || 0
ensure(whitelistOwner, 'WHITELIST_OWNER')
ensure(gasPriceOracleOwner, 'GAS_PRICE_ORACLE_OWNER')
ensure(l2BlockGasLimit, 'L2_BLOCK_GAS_LIMIT')
ensure(l2ChainId, 'L2_CHAIN_ID')
ensure(blockSignerAddress, 'BLOCK_SIGNER_ADDRESS')
ensure(l1StandardBridgeAddress, 'L1_STANDARD_BRIDGE_ADDRESS')
ensure(l1FeeWalletAddress, 'L1_FEE_WALLET_ADDRESS')
ensure(l1CrossDomainMessengerAddress, 'L1_CROSS_DOMAIN_MESSENGER_ADDRESS')
ensure(berlinBlock, 'BERLIN_BLOCK')
// Basic warning so users know that the whitelist will be disabled if the owner is the zero address.
if (env.WHITELIST_OWNER === '0x' + '00'.repeat(20)) {
console.log(
'WARNING: whitelist owner is address(0), whitelist will be disabled'
)
}
const genesis = await makeL2GenesisFile({
whitelistOwner,
gasPriceOracleOwner,
gasPriceOracleOverhead,
gasPriceOracleScalar,
gasPriceOracleL1BaseFee,
gasPriceOracleGasPrice,
gasPriceOracleDecimals,
l2BlockGasLimit,
l2ChainId,
blockSignerAddress,
l1StandardBridgeAddress,
l1FeeWalletAddress,
l1CrossDomainMessengerAddress,
berlinBlock,
})
fs.writeFileSync(outfile, JSON.stringify(genesis, null, 4))
})()
import { DeployConfig } from '../src/deploy-config'
const config: DeployConfig = {
network: 'goerli',
l1BlockTimeSeconds: 15,
l2BlockGasLimit: 15_000_000,
l2ChainId: 420,
ctcL2GasDiscountDivisor: 32,
ctcEnqueueGasCost: 60_000,
sccFaultProofWindowSeconds: 604800,
sccSequencerPublishWindowSeconds: 12592000,
ovmSequencerAddress: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
ovmProposerAddress: '0x9A2F243c605e6908D96b18e21Fb82Bf288B19EF3',
ovmBlockSignerAddress: '0x27770a9694e4B4b1E130Ab91Bc327C36855f612E',
ovmFeeWalletAddress: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
ovmAddressManagerOwner: '0x32b70c156302d28A9119445d2bbb9ab1cBD01671',
ovmGasPriceOracleOwner: '0x84f70449f90300997840eCb0918873745Ede7aE6',
}
export default config
import { DeployConfig } from '../src/deploy-config'
const config: DeployConfig = {
network: 'kovan',
numDeployConfirmations: 1,
gasPrice: 5_000_000_000,
l1BlockTimeSeconds: 15,
l2BlockGasLimit: 15_000_000,
l2ChainId: 69,
ctcL2GasDiscountDivisor: 32,
ctcEnqueueGasCost: 60_000,
sccFaultProofWindowSeconds: 10,
sccSequencerPublishWindowSeconds: 12592000,
ovmSequencerAddress: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
ovmProposerAddress: '0x9A2F243c605e6908D96b18e21Fb82Bf288B19EF3',
ovmBlockSignerAddress: '0x00000398232E2064F896018496b4b44b3D62751F',
ovmFeeWalletAddress: '0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244',
ovmAddressManagerOwner: '0x18394B52d3Cb931dfA76F63251919D051953413d',
ovmGasPriceOracleOwner: '0x84f70449f90300997840eCb0918873745Ede7aE6',
}
export default config
import { DeployConfig } from '../src/deploy-config'
const config: DeployConfig = {
network: 'local',
l1BlockTimeSeconds: 15,
l2BlockGasLimit: 15_000_000,
l2ChainId: 987,
ctcL2GasDiscountDivisor: 32,
ctcEnqueueGasCost: 60_000,
sccFaultProofWindowSeconds: 0,
sccSequencerPublishWindowSeconds: 12592000,
ovmSequencerAddress: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
ovmProposerAddress: '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc',
ovmBlockSignerAddress: '0x00000398232E2064F896018496b4b44b3D62751F',
ovmFeeWalletAddress: '0x391716d440c151c42cdf1c95c1d83a5427bca52c',
ovmAddressManagerOwner: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
ovmGasPriceOracleOwner: '0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc',
}
export default config
import { DeployConfig } from '../src/deploy-config'
const config: DeployConfig = {
network: 'mainnet',
numDeployConfirmations: 4,
gasPrice: 150_000_000_000,
l1BlockTimeSeconds: 15,
l2BlockGasLimit: 15_000_000,
l2ChainId: 10,
ctcL2GasDiscountDivisor: 32,
ctcEnqueueGasCost: 60_000,
sccFaultProofWindowSeconds: 604800,
sccSequencerPublishWindowSeconds: 12592000,
ovmSequencerAddress: '0x6887246668a3b87F54DeB3b94Ba47a6f63F32985',
ovmProposerAddress: '0x473300df21D047806A082244b417f96b32f13A33',
ovmBlockSignerAddress: '0x00000398232E2064F896018496b4b44b3D62751F',
ovmFeeWalletAddress: '0x391716d440c151c42cdf1c95c1d83a5427bca52c',
ovmAddressManagerOwner: '0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A',
ovmGasPriceOracleOwner: '0x7107142636C85c549690b1Aca12Bdb8052d26Ae6',
ovmWhitelistOwner: '0x648E3e8101BFaB7bf5997Bd007Fb473786019159',
}
export default config
...@@ -9,10 +9,12 @@ import { ...@@ -9,10 +9,12 @@ import {
sendImpersonatedTx, sendImpersonatedTx,
BIG_BALANCE, BIG_BALANCE,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
if ((hre as any).deployConfig.forked !== 'true') { const deployConfig = getDeployConfig(hre.network.name)
if (!deployConfig.isForkedNetwork) {
return return
} }
......
...@@ -2,18 +2,20 @@ ...@@ -2,18 +2,20 @@
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import { names } from '../src/address-names' import { names } from '../src/address-names'
import { getDeployConfig } from '../src/deploy-config'
/* Imports: External */ /* Imports: External */
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const { deploy } = hre.deployments const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
const deployConfig = getDeployConfig(hre.network.name)
await deploy(names.unmanaged.Lib_AddressManager, { await deploy(names.unmanaged.Lib_AddressManager, {
from: deployer, from: deployer,
args: [], args: [],
log: true, log: true,
waitConfirmations: (hre as any).deployConfig.numDeployConfirmations, waitConfirmations: deployConfig.numDeployConfirmations,
}) })
} }
......
...@@ -6,9 +6,12 @@ import { ...@@ -6,9 +6,12 @@ import {
deployAndVerifyAndThen, deployAndVerifyAndThen,
getContractFromArtifact, getContractFromArtifact,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const Lib_AddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
names.unmanaged.Lib_AddressManager names.unmanaged.Lib_AddressManager
...@@ -19,9 +22,9 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -19,9 +22,9 @@ const deployFn: DeployFunction = async (hre) => {
name: names.managed.contracts.CanonicalTransactionChain, name: names.managed.contracts.CanonicalTransactionChain,
args: [ args: [
Lib_AddressManager.address, Lib_AddressManager.address,
(hre as any).deployConfig.ctcMaxTransactionGasLimit, deployConfig.l2BlockGasLimit,
(hre as any).deployConfig.ctcL2GasDiscountDivisor, deployConfig.ctcL2GasDiscountDivisor,
(hre as any).deployConfig.ctcEnqueueGasCost, deployConfig.ctcEnqueueGasCost,
], ],
}) })
} }
......
...@@ -6,9 +6,12 @@ import { ...@@ -6,9 +6,12 @@ import {
deployAndVerifyAndThen, deployAndVerifyAndThen,
getContractFromArtifact, getContractFromArtifact,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const Lib_AddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
names.unmanaged.Lib_AddressManager names.unmanaged.Lib_AddressManager
...@@ -19,8 +22,8 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -19,8 +22,8 @@ const deployFn: DeployFunction = async (hre) => {
name: names.managed.contracts.StateCommitmentChain, name: names.managed.contracts.StateCommitmentChain,
args: [ args: [
Lib_AddressManager.address, Lib_AddressManager.address,
(hre as any).deployConfig.sccFraudProofWindow, deployConfig.sccFaultProofWindowSeconds,
(hre as any).deployConfig.sccSequencerPublishWindow, deployConfig.sccSequencerPublishWindowSeconds,
], ],
}) })
} }
......
...@@ -7,9 +7,12 @@ import { ...@@ -7,9 +7,12 @@ import {
deployAndVerifyAndThen, deployAndVerifyAndThen,
getContractFromArtifact, getContractFromArtifact,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const Lib_AddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
names.unmanaged.Lib_AddressManager names.unmanaged.Lib_AddressManager
...@@ -45,7 +48,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -45,7 +48,7 @@ const deployFn: DeployFunction = async (hre) => {
console.log( console.log(
`Transferring ownership of L1CrossDomainMessenger (implementation)...` `Transferring ownership of L1CrossDomainMessenger (implementation)...`
) )
const owner = (hre as any).deployConfig.ovmAddressManagerOwner const owner = deployConfig.ovmAddressManagerOwner
await contract.transferOwnership(owner) await contract.transferOwnership(owner)
console.log(`Checking that contract owner was correctly set...`) console.log(`Checking that contract owner was correctly set...`)
......
...@@ -7,10 +7,13 @@ import { ...@@ -7,10 +7,13 @@ import {
deployAndVerifyAndThen, deployAndVerifyAndThen,
getContractFromArtifact, getContractFromArtifact,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
import { predeploys } from '../src/predeploys' import { predeploys } from '../src/predeploys'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const Lib_AddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
names.unmanaged.Lib_AddressManager names.unmanaged.Lib_AddressManager
...@@ -42,13 +45,13 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -42,13 +45,13 @@ const deployFn: DeployFunction = async (hre) => {
// CanonicalTransactionChain. // CanonicalTransactionChain.
{ {
name: names.managed.accounts.OVM_Sequencer, name: names.managed.accounts.OVM_Sequencer,
address: (hre as any).deployConfig.ovmSequencerAddress, address: deployConfig.ovmSequencerAddress,
}, },
// OVM_Proposer is the address allowed to submit state roots (transaction results) to the // OVM_Proposer is the address allowed to submit state roots (transaction results) to the
// StateCommitmentChain. // StateCommitmentChain.
{ {
name: names.managed.accounts.OVM_Proposer, name: names.managed.accounts.OVM_Proposer,
address: (hre as any).deployConfig.ovmProposerAddress, address: deployConfig.ovmProposerAddress,
}, },
] ]
...@@ -69,7 +72,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -69,7 +72,7 @@ const deployFn: DeployFunction = async (hre) => {
name: names.unmanaged.AddressDictator, name: names.unmanaged.AddressDictator,
args: [ args: [
Lib_AddressManager.address, Lib_AddressManager.address,
(hre as any).deployConfig.ovmAddressManagerOwner, deployConfig.ovmAddressManagerOwner,
namesAndAddresses.map((pair) => { namesAndAddresses.map((pair) => {
return pair.name return pair.name
}), }),
......
...@@ -4,9 +4,11 @@ import { hexStringEquals, awaitCondition } from '@eth-optimism/core-utils' ...@@ -4,9 +4,11 @@ import { hexStringEquals, awaitCondition } from '@eth-optimism/core-utils'
/* Imports: Internal */ /* Imports: Internal */
import { getContractFromArtifact } from '../src/deploy-utils' import { getContractFromArtifact } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
// There's a risk that we could get front-run during a fresh deployment, which would brick this // There's a risk that we could get front-run during a fresh deployment, which would brick this
...@@ -43,7 +45,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -43,7 +45,7 @@ const deployFn: DeployFunction = async (hre) => {
) )
console.log(`Setting Proxy__OVM_L1CrossDomainMessenger owner...`) console.log(`Setting Proxy__OVM_L1CrossDomainMessenger owner...`)
const owner = (hre as any).deployConfig.ovmAddressManagerOwner const owner = deployConfig.ovmAddressManagerOwner
await Proxy__OVM_L1CrossDomainMessenger.transferOwnership(owner) await Proxy__OVM_L1CrossDomainMessenger.transferOwnership(owner)
console.log(`Checking that the contract owner was correctly set...`) console.log(`Checking that the contract owner was correctly set...`)
......
...@@ -9,9 +9,12 @@ import { ...@@ -9,9 +9,12 @@ import {
getContractFromArtifact, getContractFromArtifact,
deployAndVerifyAndThen, deployAndVerifyAndThen,
} from '../src/deploy-utils' } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names' import { names } from '../src/address-names'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const Proxy__OVM_L1StandardBridge = await getContractFromArtifact( const Proxy__OVM_L1StandardBridge = await getContractFromArtifact(
hre, hre,
'Proxy__OVM_L1StandardBridge' 'Proxy__OVM_L1StandardBridge'
...@@ -31,7 +34,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -31,7 +34,7 @@ const deployFn: DeployFunction = async (hre) => {
name: names.unmanaged.ChugSplashDictator, name: names.unmanaged.ChugSplashDictator,
args: [ args: [
Proxy__OVM_L1StandardBridge.address, Proxy__OVM_L1StandardBridge.address,
(hre as any).deployConfig.ovmAddressManagerOwner, deployConfig.ovmAddressManagerOwner,
ethers.utils.keccak256(bridgeCode), ethers.utils.keccak256(bridgeCode),
ethers.utils.hexZeroPad('0x00', 32), ethers.utils.hexZeroPad('0x00', 32),
ethers.utils.hexZeroPad(Proxy__OVM_L1CrossDomainMessenger.address, 32), ethers.utils.hexZeroPad(Proxy__OVM_L1CrossDomainMessenger.address, 32),
......
...@@ -4,9 +4,12 @@ import { hexStringEquals, awaitCondition } from '@eth-optimism/core-utils' ...@@ -4,9 +4,12 @@ import { hexStringEquals, awaitCondition } from '@eth-optimism/core-utils'
/* Imports: Internal */ /* Imports: Internal */
import { getContractFromArtifact } from '../src/deploy-utils' import { getContractFromArtifact } from '../src/deploy-utils'
import { getDeployConfig } from '../src/deploy-config'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const deployConfig = getDeployConfig(hre.network.name)
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
'Lib_AddressManager', 'Lib_AddressManager',
...@@ -15,7 +18,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -15,7 +18,7 @@ const deployFn: DeployFunction = async (hre) => {
} }
) )
const owner = (hre as any).deployConfig.ovmAddressManagerOwner const owner = deployConfig.ovmAddressManagerOwner
const remoteOwner = await Lib_AddressManager.owner() const remoteOwner = await Lib_AddressManager.owner()
if (hexStringEquals(owner, remoteOwner)) { if (hexStringEquals(owner, remoteOwner)) {
console.log( console.log(
......
{
"address": "0x4821975ca220601c153d02353300d6ad34adc362",
"abi": [
{
"inputs": [
{
"internalType": "uint256",
"name": "_minDepositAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_maxDepositAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_maxBalance",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "balance",
"type": "uint256"
}
],
"name": "BalanceWithdrawn",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "depositId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "emitter",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "EtherReceived",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "previousBalance",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "newBalance",
"type": "uint256"
}
],
"name": "MaxBalanceSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "previousAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "newAmount",
"type": "uint256"
}
],
"name": "MaxDepositAmountSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "previousAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "newAmount",
"type": "uint256"
}
],
"name": "MinDepositAmountSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "c__0xbf18ea64",
"type": "bytes32"
}
],
"name": "c_0xbf18ea64",
"outputs": [],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "maxBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxDepositAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "minDepositAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxDepositAmount",
"type": "uint256"
}
],
"name": "setMaxAmount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxBalance",
"type": "uint256"
}
],
"name": "setMaxBalance",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_minDepositAmount",
"type": "uint256"
}
],
"name": "setMinAmount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "totalDeposits",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdrawBalance",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
],
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"receipt": {
"to": null,
"from": "0x6c2cBc2132aB6Fc48Ebf3569Bdde7B0AA34aa0FC",
"contractAddress": "0x170E152DeDADaa7fE028b025B18748cbab7083bD",
"transactionIndex": 1,
"gasUsed": "1286769",
"logsBloom": "0x00000000000000000000000010000000000000000000000000800000000000000100000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400080000000000000000000000000000040000000000000000000000000000000000000040000000000000000000000000000000000020000000000000000000000000000000000000200000000000000400000000020000000040000000020000000000000000010000000000000008000000000000000000000000000020000",
"blockHash": "0xb2eb3e02f35921cd1201f5a5eecbdf61c6f8196b174fb057e442fc2c85d2635f",
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"logs": [
{
"transactionIndex": 1,
"blockNumber": 30510065,
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"address": "0x170E152DeDADaa7fE028b025B18748cbab7083bD",
"topics": [
"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000006c2cbc2132ab6fc48ebf3569bdde7b0aa34aa0fc"
],
"data": "0x",
"logIndex": 1,
"blockHash": "0xb2eb3e02f35921cd1201f5a5eecbdf61c6f8196b174fb057e442fc2c85d2635f"
},
{
"transactionIndex": 1,
"blockNumber": 30510065,
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"address": "0x170E152DeDADaa7fE028b025B18748cbab7083bD",
"topics": [
"0x65779d3ca560e9bdec52d08ed75431a84df87cb7796f0e51965f6efc0f556c0f"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000",
"logIndex": 2,
"blockHash": "0xb2eb3e02f35921cd1201f5a5eecbdf61c6f8196b174fb057e442fc2c85d2635f"
},
{
"transactionIndex": 1,
"blockNumber": 30510065,
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"address": "0x170E152DeDADaa7fE028b025B18748cbab7083bD",
"topics": [
"0xb1e6cc560df1786578fd4d1fe6e046f089a0c3be401e999b51a5112437911797"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000",
"logIndex": 3,
"blockHash": "0xb2eb3e02f35921cd1201f5a5eecbdf61c6f8196b174fb057e442fc2c85d2635f"
},
{
"transactionIndex": 1,
"blockNumber": 30510065,
"transactionHash": "0x83a2775ed8bc832e1a4ae46b003b5b0987a4163cc79224d65fc9c38875f0b452",
"address": "0x170E152DeDADaa7fE028b025B18748cbab7083bD",
"topics": [
"0x185c6391e7218e85de8a9346fc72024a0f88e1f04c186e6351230b93976ad50b"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003635c9adc5dea00000",
"logIndex": 4,
"blockHash": "0xb2eb3e02f35921cd1201f5a5eecbdf61c6f8196b174fb057e442fc2c85d2635f"
}
],
"blockNumber": 30510065,
"cumulativeGasUsed": "1322127",
"status": 1,
"byzantium": true
},
"args": [
"1000000000000000",
"1000000000000000000",
"1000000000000000000000"
],
"solcInputHash": "f20d616c1af6713a0e8ca9fae9d7bae7",
"metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minDepositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxDepositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"BalanceWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"emitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"EtherReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"MaxBalanceSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newAmount\",\"type\":\"uint256\"}],\"name\":\"MaxDepositAmountSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newAmount\",\"type\":\"uint256\"}],\"name\":\"MinDepositAmountSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"c__0xbf18ea64\",\"type\":\"bytes32\"}],\"name\":\"c_0xbf18ea64\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxDepositAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minDepositAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxDepositAmount\",\"type\":\"uint256\"}],\"name\":\"setMaxAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxBalance\",\"type\":\"uint256\"}],\"name\":\"setMaxBalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minDepositAmount\",\"type\":\"uint256\"}],\"name\":\"setMinAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDeposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"BalanceWithdrawn(address,uint256)\":{\"params\":{\"balance\":\"The current contract balance paid to the owner.\",\"owner\":\"The current owner and recipient of the funds.\"}},\"EtherReceived(uint256,address,uint256)\":{\"params\":{\"amount\":\"The amount deposited by the payer.\",\"depositId\":\"A unique sequencer number identifying the deposit.\",\"emitter\":\"The sending address of the payer.\"}},\"MaxBalanceSet(uint256,uint256)\":{\"params\":{\"newBalance\":\"The new maximum contract balance.\",\"previousBalance\":\"The previous maximum contract balance.\"}},\"MaxDepositAmountSet(uint256,uint256)\":{\"params\":{\"newAmount\":\"The new maximum deposit amount.\",\"previousAmount\":\"The previous maximum deposit amount.\"}},\"MinDepositAmountSet(uint256,uint256)\":{\"params\":{\"newAmount\":\"The new minimum deposit amount.\",\"previousAmount\":\"The previous minimum deposit amount.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_maxBalance\":\"The initial maximum contract balance.\",\"_maxDepositAmount\":\"The initial maximum deposit amount.\",\"_minDepositAmount\":\"The initial minimum deposit amount.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setMaxAmount(uint256)\":{\"params\":{\"_maxDepositAmount\":\"The new maximum deposit amount.\"}},\"setMaxBalance(uint256)\":{\"params\":{\"_maxBalance\":\"The new maximum contract balance.\"}},\"setMinAmount(uint256)\":{\"params\":{\"_minDepositAmount\":\"The new minimum deposit amount.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"TeleportrDeposit Shout out to 0xclem for providing the inspiration for this contract: https://github.com/0xclem/teleportr/blob/main/contracts/BridgeDeposit.sol\",\"version\":1},\"userdoc\":{\"events\":{\"BalanceWithdrawn(address,uint256)\":{\"notice\":\"Emitted any time the balance is withdrawn by the owner.\"},\"EtherReceived(uint256,address,uint256)\":{\"notice\":\"Emitted any time a successful deposit is received.\"},\"MaxBalanceSet(uint256,uint256)\":{\"notice\":\"Emitted any time the contract maximum balance is set.\"},\"MaxDepositAmountSet(uint256,uint256)\":{\"notice\":\"Emitted any time the maximum deposit amount is set.\"},\"MinDepositAmountSet(uint256,uint256)\":{\"notice\":\"Emitted any time the minimum deposit amount is set.\"}},\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initializes a new TeleportrDeposit contract.\"},\"maxBalance()\":{\"notice\":\"The maximum balance the contract can hold after a receive.\"},\"maxDepositAmount()\":{\"notice\":\"The maximum amount that be deposited in a receive.\"},\"minDepositAmount()\":{\"notice\":\"The minimum amount that be deposited in a receive.\"},\"setMaxAmount(uint256)\":{\"notice\":\"Sets the maximum amount that can be deposited in a receive.\"},\"setMaxBalance(uint256)\":{\"notice\":\"Sets the maximum balance the contract can hold after a receive.\"},\"setMinAmount(uint256)\":{\"notice\":\"Sets the minimum amount that can be deposited in a receive.\"},\"totalDeposits()\":{\"notice\":\"The total number of successful deposits received.\"},\"withdrawBalance()\":{\"notice\":\"Sends the contract's current balance to the owner.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1/teleportr/TeleportrDeposit.sol\":\"TeleportrDeposit\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0x6bb804a310218875e89d12c053e94a13a4607cdf7cc2052f3e52bd32a0dc50a1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2ebbbe6d0011175bd9e7268b83de3f9c2f9d8d4cbfbaef12aff977d7d727163\",\"dweb:/ipfs/Qmd5c7Vxtis9wzkDNhxwc6A2QT5H9xn9kfjhx7qx44vpro\"]},\"@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26e8b38a7ac8e7b4463af00cf7fff1bf48ae9875765bf4f7751e100124d0bc8c\",\"dweb:/ipfs/QmWcsmkVr24xmmjfnBQZoemFniXjj3vwT78Cz6uqZW1Hux\"]},\"contracts/L1/teleportr/TeleportrDeposit.sol\":{\"keccak256\":\"0x885673d5837399f19082826a2bc64889384a39f0999d003bfcca675a26ec2d74\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d44b9d501288828c6fa026eaa02936301ff0e2037294747d7c1605fa93a598e0\",\"dweb:/ipfs/QmbQ2pQnvkTzuwns4azKVPmKvB2oPV6rJ6wL3ZE3vw6n15\"]}},\"version\":1}",
"bytecode": "0x60806040523480156200001157600080fd5b5060405162001a6a38038062001a6a83398181016040528101906200003791906200054b565b620000576200004b6200043c60201b60201c565b6200044460201b60201c565b6200008a7e64b7c3d2e027eba5da5f5280491bfce7932df45fdf2e0891110c3dc3e84bf460001b6200050860201b60201c565b620000be7f0754617f84d3b5fc04f16a0983e82c729cb6d2698f728b30dfa934b5add9016960001b6200050860201b60201c565b620000f27f1cd5d3f0acece0d68e6ccf8bfd89b818133486ea9f082a4b9b7b11b6000baad560001b6200050860201b60201c565b826001819055506200012d7f30791823e64606c8be3e7feb8b103685a5aaff26eaa6bd2c7f3ce310352527be60001b6200050860201b60201c565b620001617f33d8a274a292fb8ba3cc7d2b767284bf7dc0c506646d5443215dab914e4ca6e860001b6200050860201b60201c565b816002819055506200019c7f50d9a49460146742cae39d07048c68aa13de2a770bed641810140d7a8973a70d60001b6200050860201b60201c565b620001d07f3d77b70ed2057214d5cd1b0ee90db5bba75d46a8e2c1c1175b1c3c6c7477c14260001b6200050860201b60201c565b806003819055506200020b7f942240fbaf8b00e69532f2fbe4ea09bf8f15876f36c4a0d73a3ece54aa0a522960001b6200050860201b60201c565b6200023f7f94060d265c2e1f35f4230c634aaf7f14185d0a42d6d8d5f35fe5492ece57cc0c60001b6200050860201b60201c565b60006004819055506200027b7f2c650db3dc7a065d861e08f687272c0e3d1fd605cd167042d67953202666742f60001b6200050860201b60201c565b620002af7f1b7587159c5f1160ede69f194a9e5c933514c192042fd3415bf2deb3f8f74b0760001b6200050860201b60201c565b7f65779d3ca560e9bdec52d08ed75431a84df87cb7796f0e51965f6efc0f556c0f600084604051620002e392919062000605565b60405180910390a16200031f7f14fdcec951a67568c0b528dd486521f51bdc14f531d71f850fa0bd2d9c45829460001b6200050860201b60201c565b620003537f59bcf0476adddb53cd05f64c33dcc191fa4a0a2cbb042239cce51dd2fc7b4b9a60001b6200050860201b60201c565b7fb1e6cc560df1786578fd4d1fe6e046f089a0c3be401e999b51a51124379117976000836040516200038792919062000605565b60405180910390a1620003c37fd10cdaddea1cf4d5c38c657c8184253dab5a819c5e4b0c88869a9564fd4b4c4960001b6200050860201b60201c565b620003f77fd8d1727cb6b16868521109e26db98e2148155c06bb992b0a0cb83f313921eb9160001b6200050860201b60201c565b7f185c6391e7218e85de8a9346fc72024a0f88e1f04c186e6351230b93976ad50b6000826040516200042b92919062000605565b60405180910390a150505062000632565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b50565b600080fd5b6000819050919050565b620005258162000510565b81146200053157600080fd5b50565b60008151905062000545816200051a565b92915050565b6000806000606084860312156200056757620005666200050b565b5b6000620005778682870162000534565b93505060206200058a8682870162000534565b92505060406200059d8682870162000534565b9150509250925092565b6000819050919050565b6000819050919050565b6000620005dc620005d6620005d084620005a7565b620005b1565b62000510565b9050919050565b620005ee81620005bb565b82525050565b620005ff8162000510565b82525050565b60006040820190506200061c6000830185620005e3565b6200062b6020830184620005f4565b9392505050565b61142880620006426000396000f3fe6080604052600436106100cb5760003560e01c80637d882097116100745780638ed832711161004e5780638ed83271146105365780639d51d9b714610561578063f2fde38b1461058a576103dc565b80637d882097146104b7578063897b0637146104e25780638da5cb5b1461050b576103dc565b8063715018a6116100a5578063715018a61461044c57806373ad468a146104635780637d63d0cd1461048e576103dc565b80634fe47f70146103e15780635fd8c7101461040a578063645006ca14610421576103dc565b366103dc576100fc7f5e91eb4e146243c5fc10218c63813d75795efa063ee048a70076cb6ecc61587d60001b6105b3565b6101287f73260b5f05e45d61e42c373897b87998b1a5a7bd70f9af562c4b361e04f0379d60001b6105b3565b60015434101561016d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161016490611029565b60405180910390fd5b6101997f23991968fdcb96adbea8af7b4742a78253230d9f76ee5eff35c987310043166a60001b6105b3565b6101c57f249aaae9e0e29e3e4031f40b7d96a68f16ea91f027ace995e46bfdaeffc6f39160001b6105b3565b6101f17fbce8df54e38e3ccc6f9f6481c255cd9804ade53c913156b5c2da09a92946cb2360001b6105b3565b600254341115610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90611095565b60405180910390fd5b6102627f2bd55ff7de06b7bc9a18ccd9faec6cc761628852dff2df2d03f1f08dc28285d660001b6105b3565b61028e7f8ad51416e28945719acfb674a9f9e6907225e745b1f9e523e751b4be1bdaac4e60001b6105b3565b6102ba7fff12f46047487761ec7b26043d01a917e9aecfcdd47cd91d771c8ea30d37e8b860001b6105b3565b6003544711156102ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f690611101565b60405180910390fd5b61032a7e3763c76368796ee311ec1b0ddfd3708e87b99464363f5ac0147716b637edb160001b6105b3565b6103567f79e71c65a22716d1eba9afec74511a85d8fe55b5f6a98109655aaf23bbcf27f060001b6105b3565b343373ffffffffffffffffffffffffffffffffffffffff166004547f2d27851832fcac28a0d4af1344f01fed7ffcfd15171c14c564a0c42aa57ae5c060405160405180910390a46103c97f1da34b6132b7d28e2dd5dcc9cc69abac10b228d460afab0c9cfbc955300ed96c60001b6105b3565b6001600460008282540192505081905550005b600080fd5b3480156103ed57600080fd5b506104086004803603810190610403919061115c565b6105b6565b005b34801561041657600080fd5b5061041f610753565b005b34801561042d57600080fd5b50610436610a05565b6040516104439190611198565b60405180910390f35b34801561045857600080fd5b50610461610a0b565b005b34801561046f57600080fd5b50610478610a93565b6040516104859190611198565b60405180910390f35b34801561049a57600080fd5b506104b560048036038101906104b091906111e9565b6105b3565b005b3480156104c357600080fd5b506104cc610a99565b6040516104d99190611198565b60405180910390f35b3480156104ee57600080fd5b506105096004803603810190610504919061115c565b610a9f565b005b34801561051757600080fd5b50610520610c3c565b60405161052d9190611257565b60405180910390f35b34801561054257600080fd5b5061054b610c65565b6040516105589190611198565b60405180910390f35b34801561056d57600080fd5b506105886004803603810190610583919061115c565b610c6b565b005b34801561059657600080fd5b506105b160048036038101906105ac919061129e565b610e08565b005b50565b6105be610f00565b73ffffffffffffffffffffffffffffffffffffffff166105dc610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062990611317565b60405180910390fd5b61065e7ffee123fad7ec16093a6435cf2c5d00b4571ad879afd34fb5bbb0d90914f7898160001b6105b3565b61068a7f23b16a5b6e035bf28fefd8536d3d907084332ed11eaad0c731ab33bdf63728ab60001b6105b3565b6106b67fe3990e89e60d0565ab8d3b4f20893f23ea714ef00b2b971bfdca4ed564f9d7bc60001b6105b3565b7fb1e6cc560df1786578fd4d1fe6e046f089a0c3be401e999b51a5112437911797600254826040516106e9929190611337565b60405180910390a161071d7f7dcc232dd4ea9159fcc353f5151cc835e78ec60204ecd0bd7d926246ba5419ab60001b6105b3565b6107497fe638d78dd410ed0ed44e18bb848eaffdebe2397f929549a92d78c434746b5a1960001b6105b3565b8060028190555050565b61075b610f00565b73ffffffffffffffffffffffffffffffffffffffff16610779610c3c565b73ffffffffffffffffffffffffffffffffffffffff16146107cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c690611317565b60405180910390fd5b6107fb7fc6b27d465e4053b68a3388de9da95b673c18eb4989d1008c2e06915f910a066060001b6105b3565b6108277f2fca1e77c51979dc28ae8dc9fc4db5c9ce9be137728cb0a61cecdd0d78850eb160001b6105b3565b6108537fec90bc2e2104a1823652f6828778f93075a8d31d8e3ac2bfd179ffcbfe51739b60001b6105b3565b600061085d610c3c565b905061088b7fb45dbc3fc05181c7356e9244306dddabaf0b75b05688c615d0e7a4833ce1b98860001b6105b3565b6108b77fbc38348ea4a9b5cb61c62ee5badf6ec802094b56806baef5ac173cb7461a82d160001b6105b3565b60004790506108e87ff96c8825c2177b3c21775b49f255faad2ce4e7da2e10326bacd5248e8b712dff60001b6105b3565b6109147fd43f2aaa632b9ffeb71c574863f0f8a1552a8f75769c81b9552396c6190eff4160001b6105b3565b8173ffffffffffffffffffffffffffffffffffffffff167fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f18260405161095a9190611198565b60405180910390a261098e7f3c0d0013f3a63b85c4bd529a45060dc1444fc884d2c8cc3cc575aa3a4710e27860001b6105b3565b6109ba7f5b79781fe133b568105927be0b812215d4bec71e3c2215d5d4758c9bac65c62760001b6105b3565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610a00573d6000803e3d6000fd5b505050565b60015481565b610a13610f00565b73ffffffffffffffffffffffffffffffffffffffff16610a31610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90611317565b60405180910390fd5b610a916000610f08565b565b60035481565b60045481565b610aa7610f00565b73ffffffffffffffffffffffffffffffffffffffff16610ac5610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1290611317565b60405180910390fd5b610b477fb433caf62ec08507ab7af9b492ca9c31d5bcdd278f6004a28794eb4106b5cf3e60001b6105b3565b610b737f897c1d74774bdd740f697ebe75144626bd7a18205b591e95d5ad4f8de174ea7060001b6105b3565b610b9f7fd9e9dc42b180f2f843f8d913ef4d43c5f8f8bea2ec782b7a740d2561a257cde260001b6105b3565b7f65779d3ca560e9bdec52d08ed75431a84df87cb7796f0e51965f6efc0f556c0f60015482604051610bd2929190611337565b60405180910390a1610c067f8da41a211fc748f0027d0993815cc4ca3cc376d4ae4b4471d749b0984a57239960001b6105b3565b610c327f4aa4ae558612ce08434cb24e0473deb7e6c2752c6a90ce39f24fd88b9cfe6d7d60001b6105b3565b8060018190555050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60025481565b610c73610f00565b73ffffffffffffffffffffffffffffffffffffffff16610c91610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610ce7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cde90611317565b60405180910390fd5b610d137fce1bcd2174ef6ef3da0e36105bd18a71486b853321242fc762fb2a5064cb2e5360001b6105b3565b610d3f7f96e568f68ceba0bb138445fe1d28ff043c88b4482d666e86c6663627a794d00e60001b6105b3565b610d6b7f83921b77b4f8764a56568881a61495190986808cf7eaa1d617e46cd7e7b52f7360001b6105b3565b7f185c6391e7218e85de8a9346fc72024a0f88e1f04c186e6351230b93976ad50b60035482604051610d9e929190611337565b60405180910390a1610dd27f5e9d45d2a21d81f43304c5d88d8c4b9fe0060aae15b5abf9547f24437e7f90fc60001b6105b3565b610dfe7f819805374cc1d4a4ad5b35e7e174e0b0ecb50f725597510954c8cd97e051b56760001b6105b3565b8060038190555050565b610e10610f00565b73ffffffffffffffffffffffffffffffffffffffff16610e2e610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b90611317565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eeb906113d2565b60405180910390fd5b610efd81610f08565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600082825260208201905092915050565b7f4465706f73697420616d6f756e7420697320746f6f20736d616c6c0000000000600082015250565b6000611013601b83610fcc565b915061101e82610fdd565b602082019050919050565b6000602082019050818103600083015261104281611006565b9050919050565b7f4465706f73697420616d6f756e7420697320746f6f2062696700000000000000600082015250565b600061107f601983610fcc565b915061108a82611049565b602082019050919050565b600060208201905081810360008301526110ae81611072565b9050919050565b7f436f6e7472616374206d61782062616c616e6365206578636565646564000000600082015250565b60006110eb601d83610fcc565b91506110f6826110b5565b602082019050919050565b6000602082019050818103600083015261111a816110de565b9050919050565b600080fd5b6000819050919050565b61113981611126565b811461114457600080fd5b50565b60008135905061115681611130565b92915050565b60006020828403121561117257611171611121565b5b600061118084828501611147565b91505092915050565b61119281611126565b82525050565b60006020820190506111ad6000830184611189565b92915050565b6000819050919050565b6111c6816111b3565b81146111d157600080fd5b50565b6000813590506111e3816111bd565b92915050565b6000602082840312156111ff576111fe611121565b5b600061120d848285016111d4565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061124182611216565b9050919050565b61125181611236565b82525050565b600060208201905061126c6000830184611248565b92915050565b61127b81611236565b811461128657600080fd5b50565b60008135905061129881611272565b92915050565b6000602082840312156112b4576112b3611121565b5b60006112c284828501611289565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000611301602083610fcc565b915061130c826112cb565b602082019050919050565b60006020820190508181036000830152611330816112f4565b9050919050565b600060408201905061134c6000830185611189565b6113596020830184611189565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006113bc602683610fcc565b91506113c782611360565b604082019050919050565b600060208201905081810360008301526113eb816113af565b905091905056fea264697066735822122037015225a63ecab5a43f7590abb54032a0ddd923e67369b73360917b27c6e14c64736f6c63430008090033",
"deployedBytecode": "0x6080604052600436106100cb5760003560e01c80637d882097116100745780638ed832711161004e5780638ed83271146105365780639d51d9b714610561578063f2fde38b1461058a576103dc565b80637d882097146104b7578063897b0637146104e25780638da5cb5b1461050b576103dc565b8063715018a6116100a5578063715018a61461044c57806373ad468a146104635780637d63d0cd1461048e576103dc565b80634fe47f70146103e15780635fd8c7101461040a578063645006ca14610421576103dc565b366103dc576100fc7f5e91eb4e146243c5fc10218c63813d75795efa063ee048a70076cb6ecc61587d60001b6105b3565b6101287f73260b5f05e45d61e42c373897b87998b1a5a7bd70f9af562c4b361e04f0379d60001b6105b3565b60015434101561016d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161016490611029565b60405180910390fd5b6101997f23991968fdcb96adbea8af7b4742a78253230d9f76ee5eff35c987310043166a60001b6105b3565b6101c57f249aaae9e0e29e3e4031f40b7d96a68f16ea91f027ace995e46bfdaeffc6f39160001b6105b3565b6101f17fbce8df54e38e3ccc6f9f6481c255cd9804ade53c913156b5c2da09a92946cb2360001b6105b3565b600254341115610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022d90611095565b60405180910390fd5b6102627f2bd55ff7de06b7bc9a18ccd9faec6cc761628852dff2df2d03f1f08dc28285d660001b6105b3565b61028e7f8ad51416e28945719acfb674a9f9e6907225e745b1f9e523e751b4be1bdaac4e60001b6105b3565b6102ba7fff12f46047487761ec7b26043d01a917e9aecfcdd47cd91d771c8ea30d37e8b860001b6105b3565b6003544711156102ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f690611101565b60405180910390fd5b61032a7e3763c76368796ee311ec1b0ddfd3708e87b99464363f5ac0147716b637edb160001b6105b3565b6103567f79e71c65a22716d1eba9afec74511a85d8fe55b5f6a98109655aaf23bbcf27f060001b6105b3565b343373ffffffffffffffffffffffffffffffffffffffff166004547f2d27851832fcac28a0d4af1344f01fed7ffcfd15171c14c564a0c42aa57ae5c060405160405180910390a46103c97f1da34b6132b7d28e2dd5dcc9cc69abac10b228d460afab0c9cfbc955300ed96c60001b6105b3565b6001600460008282540192505081905550005b600080fd5b3480156103ed57600080fd5b506104086004803603810190610403919061115c565b6105b6565b005b34801561041657600080fd5b5061041f610753565b005b34801561042d57600080fd5b50610436610a05565b6040516104439190611198565b60405180910390f35b34801561045857600080fd5b50610461610a0b565b005b34801561046f57600080fd5b50610478610a93565b6040516104859190611198565b60405180910390f35b34801561049a57600080fd5b506104b560048036038101906104b091906111e9565b6105b3565b005b3480156104c357600080fd5b506104cc610a99565b6040516104d99190611198565b60405180910390f35b3480156104ee57600080fd5b506105096004803603810190610504919061115c565b610a9f565b005b34801561051757600080fd5b50610520610c3c565b60405161052d9190611257565b60405180910390f35b34801561054257600080fd5b5061054b610c65565b6040516105589190611198565b60405180910390f35b34801561056d57600080fd5b506105886004803603810190610583919061115c565b610c6b565b005b34801561059657600080fd5b506105b160048036038101906105ac919061129e565b610e08565b005b50565b6105be610f00565b73ffffffffffffffffffffffffffffffffffffffff166105dc610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062990611317565b60405180910390fd5b61065e7ffee123fad7ec16093a6435cf2c5d00b4571ad879afd34fb5bbb0d90914f7898160001b6105b3565b61068a7f23b16a5b6e035bf28fefd8536d3d907084332ed11eaad0c731ab33bdf63728ab60001b6105b3565b6106b67fe3990e89e60d0565ab8d3b4f20893f23ea714ef00b2b971bfdca4ed564f9d7bc60001b6105b3565b7fb1e6cc560df1786578fd4d1fe6e046f089a0c3be401e999b51a5112437911797600254826040516106e9929190611337565b60405180910390a161071d7f7dcc232dd4ea9159fcc353f5151cc835e78ec60204ecd0bd7d926246ba5419ab60001b6105b3565b6107497fe638d78dd410ed0ed44e18bb848eaffdebe2397f929549a92d78c434746b5a1960001b6105b3565b8060028190555050565b61075b610f00565b73ffffffffffffffffffffffffffffffffffffffff16610779610c3c565b73ffffffffffffffffffffffffffffffffffffffff16146107cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c690611317565b60405180910390fd5b6107fb7fc6b27d465e4053b68a3388de9da95b673c18eb4989d1008c2e06915f910a066060001b6105b3565b6108277f2fca1e77c51979dc28ae8dc9fc4db5c9ce9be137728cb0a61cecdd0d78850eb160001b6105b3565b6108537fec90bc2e2104a1823652f6828778f93075a8d31d8e3ac2bfd179ffcbfe51739b60001b6105b3565b600061085d610c3c565b905061088b7fb45dbc3fc05181c7356e9244306dddabaf0b75b05688c615d0e7a4833ce1b98860001b6105b3565b6108b77fbc38348ea4a9b5cb61c62ee5badf6ec802094b56806baef5ac173cb7461a82d160001b6105b3565b60004790506108e87ff96c8825c2177b3c21775b49f255faad2ce4e7da2e10326bacd5248e8b712dff60001b6105b3565b6109147fd43f2aaa632b9ffeb71c574863f0f8a1552a8f75769c81b9552396c6190eff4160001b6105b3565b8173ffffffffffffffffffffffffffffffffffffffff167fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f18260405161095a9190611198565b60405180910390a261098e7f3c0d0013f3a63b85c4bd529a45060dc1444fc884d2c8cc3cc575aa3a4710e27860001b6105b3565b6109ba7f5b79781fe133b568105927be0b812215d4bec71e3c2215d5d4758c9bac65c62760001b6105b3565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610a00573d6000803e3d6000fd5b505050565b60015481565b610a13610f00565b73ffffffffffffffffffffffffffffffffffffffff16610a31610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90611317565b60405180910390fd5b610a916000610f08565b565b60035481565b60045481565b610aa7610f00565b73ffffffffffffffffffffffffffffffffffffffff16610ac5610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1290611317565b60405180910390fd5b610b477fb433caf62ec08507ab7af9b492ca9c31d5bcdd278f6004a28794eb4106b5cf3e60001b6105b3565b610b737f897c1d74774bdd740f697ebe75144626bd7a18205b591e95d5ad4f8de174ea7060001b6105b3565b610b9f7fd9e9dc42b180f2f843f8d913ef4d43c5f8f8bea2ec782b7a740d2561a257cde260001b6105b3565b7f65779d3ca560e9bdec52d08ed75431a84df87cb7796f0e51965f6efc0f556c0f60015482604051610bd2929190611337565b60405180910390a1610c067f8da41a211fc748f0027d0993815cc4ca3cc376d4ae4b4471d749b0984a57239960001b6105b3565b610c327f4aa4ae558612ce08434cb24e0473deb7e6c2752c6a90ce39f24fd88b9cfe6d7d60001b6105b3565b8060018190555050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60025481565b610c73610f00565b73ffffffffffffffffffffffffffffffffffffffff16610c91610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610ce7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cde90611317565b60405180910390fd5b610d137fce1bcd2174ef6ef3da0e36105bd18a71486b853321242fc762fb2a5064cb2e5360001b6105b3565b610d3f7f96e568f68ceba0bb138445fe1d28ff043c88b4482d666e86c6663627a794d00e60001b6105b3565b610d6b7f83921b77b4f8764a56568881a61495190986808cf7eaa1d617e46cd7e7b52f7360001b6105b3565b7f185c6391e7218e85de8a9346fc72024a0f88e1f04c186e6351230b93976ad50b60035482604051610d9e929190611337565b60405180910390a1610dd27f5e9d45d2a21d81f43304c5d88d8c4b9fe0060aae15b5abf9547f24437e7f90fc60001b6105b3565b610dfe7f819805374cc1d4a4ad5b35e7e174e0b0ecb50f725597510954c8cd97e051b56760001b6105b3565b8060038190555050565b610e10610f00565b73ffffffffffffffffffffffffffffffffffffffff16610e2e610c3c565b73ffffffffffffffffffffffffffffffffffffffff1614610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b90611317565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eeb906113d2565b60405180910390fd5b610efd81610f08565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600082825260208201905092915050565b7f4465706f73697420616d6f756e7420697320746f6f20736d616c6c0000000000600082015250565b6000611013601b83610fcc565b915061101e82610fdd565b602082019050919050565b6000602082019050818103600083015261104281611006565b9050919050565b7f4465706f73697420616d6f756e7420697320746f6f2062696700000000000000600082015250565b600061107f601983610fcc565b915061108a82611049565b602082019050919050565b600060208201905081810360008301526110ae81611072565b9050919050565b7f436f6e7472616374206d61782062616c616e6365206578636565646564000000600082015250565b60006110eb601d83610fcc565b91506110f6826110b5565b602082019050919050565b6000602082019050818103600083015261111a816110de565b9050919050565b600080fd5b6000819050919050565b61113981611126565b811461114457600080fd5b50565b60008135905061115681611130565b92915050565b60006020828403121561117257611171611121565b5b600061118084828501611147565b91505092915050565b61119281611126565b82525050565b60006020820190506111ad6000830184611189565b92915050565b6000819050919050565b6111c6816111b3565b81146111d157600080fd5b50565b6000813590506111e3816111bd565b92915050565b6000602082840312156111ff576111fe611121565b5b600061120d848285016111d4565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061124182611216565b9050919050565b61125181611236565b82525050565b600060208201905061126c6000830184611248565b92915050565b61127b81611236565b811461128657600080fd5b50565b60008135905061129881611272565b92915050565b6000602082840312156112b4576112b3611121565b5b60006112c284828501611289565b91505092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000611301602083610fcc565b915061130c826112cb565b602082019050919050565b60006020820190508181036000830152611330816112f4565b9050919050565b600060408201905061134c6000830185611189565b6113596020830184611189565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006113bc602683610fcc565b91506113c782611360565b604082019050919050565b600060208201905081810360008301526113eb816113af565b905091905056fea264697066735822122037015225a63ecab5a43f7590abb54032a0ddd923e67369b73360917b27c6e14c64736f6c63430008090033",
"devdoc": {
"events": {
"BalanceWithdrawn(address,uint256)": {
"params": {
"balance": "The current contract balance paid to the owner.",
"owner": "The current owner and recipient of the funds."
}
},
"EtherReceived(uint256,address,uint256)": {
"params": {
"amount": "The amount deposited by the payer.",
"depositId": "A unique sequencer number identifying the deposit.",
"emitter": "The sending address of the payer."
}
},
"MaxBalanceSet(uint256,uint256)": {
"params": {
"newBalance": "The new maximum contract balance.",
"previousBalance": "The previous maximum contract balance."
}
},
"MaxDepositAmountSet(uint256,uint256)": {
"params": {
"newAmount": "The new maximum deposit amount.",
"previousAmount": "The previous maximum deposit amount."
}
},
"MinDepositAmountSet(uint256,uint256)": {
"params": {
"newAmount": "The new minimum deposit amount.",
"previousAmount": "The previous minimum deposit amount."
}
}
},
"kind": "dev",
"methods": {
"constructor": {
"params": {
"_maxBalance": "The initial maximum contract balance.",
"_maxDepositAmount": "The initial maximum deposit amount.",
"_minDepositAmount": "The initial minimum deposit amount."
}
},
"owner()": {
"details": "Returns the address of the current owner."
},
"renounceOwnership()": {
"details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."
},
"setMaxAmount(uint256)": {
"params": {
"_maxDepositAmount": "The new maximum deposit amount."
}
},
"setMaxBalance(uint256)": {
"params": {
"_maxBalance": "The new maximum contract balance."
}
},
"setMinAmount(uint256)": {
"params": {
"_minDepositAmount": "The new minimum deposit amount."
}
},
"transferOwnership(address)": {
"details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
}
},
"title": "TeleportrDeposit Shout out to 0xclem for providing the inspiration for this contract: https://github.com/0xclem/teleportr/blob/main/contracts/BridgeDeposit.sol",
"version": 1
},
"userdoc": {
"events": {
"BalanceWithdrawn(address,uint256)": {
"notice": "Emitted any time the balance is withdrawn by the owner."
},
"EtherReceived(uint256,address,uint256)": {
"notice": "Emitted any time a successful deposit is received."
},
"MaxBalanceSet(uint256,uint256)": {
"notice": "Emitted any time the contract maximum balance is set."
},
"MaxDepositAmountSet(uint256,uint256)": {
"notice": "Emitted any time the maximum deposit amount is set."
},
"MinDepositAmountSet(uint256,uint256)": {
"notice": "Emitted any time the minimum deposit amount is set."
}
},
"kind": "user",
"methods": {
"constructor": {
"notice": "Initializes a new TeleportrDeposit contract."
},
"maxBalance()": {
"notice": "The maximum balance the contract can hold after a receive."
},
"maxDepositAmount()": {
"notice": "The maximum amount that be deposited in a receive."
},
"minDepositAmount()": {
"notice": "The minimum amount that be deposited in a receive."
},
"setMaxAmount(uint256)": {
"notice": "Sets the maximum amount that can be deposited in a receive."
},
"setMaxBalance(uint256)": {
"notice": "Sets the maximum balance the contract can hold after a receive."
},
"setMinAmount(uint256)": {
"notice": "Sets the minimum amount that can be deposited in a receive."
},
"totalDeposits()": {
"notice": "The total number of successful deposits received."
},
"withdrawBalance()": {
"notice": "Sends the contract's current balance to the owner."
}
},
"version": 1
},
"storageLayout": {
"storage": [
{
"astId": 393,
"contract": "contracts/L1/teleportr/TeleportrDeposit.sol:TeleportrDeposit",
"label": "_owner",
"offset": 0,
"slot": "0",
"type": "t_address"
},
{
"astId": 7830,
"contract": "contracts/L1/teleportr/TeleportrDeposit.sol:TeleportrDeposit",
"label": "minDepositAmount",
"offset": 0,
"slot": "1",
"type": "t_uint256"
},
{
"astId": 7833,
"contract": "contracts/L1/teleportr/TeleportrDeposit.sol:TeleportrDeposit",
"label": "maxDepositAmount",
"offset": 0,
"slot": "2",
"type": "t_uint256"
},
{
"astId": 7836,
"contract": "contracts/L1/teleportr/TeleportrDeposit.sol:TeleportrDeposit",
"label": "maxBalance",
"offset": 0,
"slot": "3",
"type": "t_uint256"
},
{
"astId": 7839,
"contract": "contracts/L1/teleportr/TeleportrDeposit.sol:TeleportrDeposit",
"label": "totalDeposits",
"offset": 0,
"slot": "4",
"type": "t_uint256"
}
],
"types": {
"t_address": {
"encoding": "inplace",
"label": "address",
"numberOfBytes": "20"
},
"t_uint256": {
"encoding": "inplace",
"label": "uint256",
"numberOfBytes": "32"
}
}
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"address": "0x4821975ca220601c153d02353300d6ad34adc362",
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "balance",
"type": "uint256"
}
],
"name": "BalanceWithdrawn",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "depositId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "DisbursementFailed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "depositId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "DisbursementSuccess",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "c__0x16931334",
"type": "bytes32"
}
],
"name": "c_0x16931334",
"outputs": [],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_nextDepositId",
"type": "uint256"
},
{
"components": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "addr",
"type": "address"
}
],
"internalType": "struct TeleportrDisburser.Disbursement[]",
"name": "_disbursements",
"type": "tuple[]"
}
],
"name": "disburse",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "totalDisbursements",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdrawBalance",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"transactionHash": "0x91be8d4c1a357b2c06bac93ce2a39015504cdd13910b0b05403bd11f8b5259c8",
"receipt": {
"to": null,
"from": "0x6c2cBc2132aB6Fc48Ebf3569Bdde7B0AA34aa0FC",
"contractAddress": "0xde440ADa095F36835ecB90297D22Ccbe02045a94",
"transactionIndex": 0,
"gasUsed": "1341401",
"logsBloom": "0x00000000000000000000000010000000000000000000000000800000000000010000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000100000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000010000000000000000000000000000000000000000000000000",
"blockHash": "0x94f294a93fc7178f06afbe6f97c0c013bbf570016ad491583af420c1d3f21763",
"transactionHash": "0x91be8d4c1a357b2c06bac93ce2a39015504cdd13910b0b05403bd11f8b5259c8",
"logs": [
{
"transactionIndex": 0,
"blockNumber": 1644547,
"transactionHash": "0x91be8d4c1a357b2c06bac93ce2a39015504cdd13910b0b05403bd11f8b5259c8",
"address": "0xde440ADa095F36835ecB90297D22Ccbe02045a94",
"topics": [
"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000006c2cbc2132ab6fc48ebf3569bdde7b0aa34aa0fc"
],
"data": "0x",
"logIndex": 0,
"blockHash": "0x94f294a93fc7178f06afbe6f97c0c013bbf570016ad491583af420c1d3f21763"
}
],
"blockNumber": 1644547,
"cumulativeGasUsed": "1341401",
"status": 1,
"byzantium": true
},
"args": [],
"solcInputHash": "f20d616c1af6713a0e8ca9fae9d7bae7",
"metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"BalanceWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"depositId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DisbursementSuccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"c__0x16931334\",\"type\":\"bytes32\"}],\"name\":\"c_0x16931334\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nextDepositId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"internalType\":\"struct TeleportrDisburser.Disbursement[]\",\"name\":\"_disbursements\",\"type\":\"tuple[]\"}],\"name\":\"disburse\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalDisbursements\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawBalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"BalanceWithdrawn(address,uint256)\":{\"params\":{\"balance\":\"The current contract balance paid to the owner.\",\"owner\":\"The current owner and recipient of the funds.\"}},\"DisbursementFailed(uint256,address,uint256)\":{\"params\":{\"amount\":\"The amount intended to be sent to the recipient.\",\"depositId\":\"The unique sequence number identifying the deposit.\",\"to\":\"The intended recipient of the disbursement.\"}},\"DisbursementSuccess(uint256,address,uint256)\":{\"params\":{\"amount\":\"The amount sent to the recipient.\",\"depositId\":\"The unique sequence number identifying the deposit.\",\"to\":\"The recipient of the disbursement.\"}}},\"kind\":\"dev\",\"methods\":{\"disburse(uint256,(uint256,address)[])\":{\"params\":{\"_disbursements\":\"A list of Disbursements to process.\",\"_nextDepositId\":\"The depositId of the first Dispursement.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"TeleportrDisburser\",\"version\":1},\"userdoc\":{\"events\":{\"BalanceWithdrawn(address,uint256)\":{\"notice\":\"Emitted any time the balance is withdrawn by the owner.\"},\"DisbursementFailed(uint256,address,uint256)\":{\"notice\":\"Emitted any time a disbursement fails to send.\"},\"DisbursementSuccess(uint256,address,uint256)\":{\"notice\":\"Emitted any time a disbursement is successfuly sent.\"}},\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Initializes a new TeleportrDisburser contract.\"},\"disburse(uint256,(uint256,address)[])\":{\"notice\":\"Accepts a list of Disbursements and forwards the amount paid to the contract to each recipient. The method reverts if there are zero disbursements, the total amount to forward differs from the amount sent in the transaction, or the _nextDepositId is unexpected. Failed disbursements will not cause the method to revert, but will instead be held by the contract and availabe for the owner to withdraw.\"},\"totalDisbursements()\":{\"notice\":\"The total number of disbursements processed.\"},\"withdrawBalance()\":{\"notice\":\"Sends the contract's current balance to the owner.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/teleportr/TeleportrDisburser.sol\":\"TeleportrDisburser\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0x6bb804a310218875e89d12c053e94a13a4607cdf7cc2052f3e52bd32a0dc50a1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2ebbbe6d0011175bd9e7268b83de3f9c2f9d8d4cbfbaef12aff977d7d727163\",\"dweb:/ipfs/Qmd5c7Vxtis9wzkDNhxwc6A2QT5H9xn9kfjhx7qx44vpro\"]},\"@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26e8b38a7ac8e7b4463af00cf7fff1bf48ae9875765bf4f7751e100124d0bc8c\",\"dweb:/ipfs/QmWcsmkVr24xmmjfnBQZoemFniXjj3vwT78Cz6uqZW1Hux\"]},\"contracts/L2/teleportr/TeleportrDisburser.sol\":{\"keccak256\":\"0x42a2eb0f230f8b713fb97d6d44330251c067a26344439cb8fc0f6c5008c61e69\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5b3f82df2740a5b40c30fca65cbf6d3242bbf34260a266cf579ef015235af676\",\"dweb:/ipfs/QmZyfQh3M3fzGMjrF31NcAG3YpxMGW93mNzVHcxfjo29qt\"]}},\"version\":1}",
"bytecode": "0x60806040523480156200001157600080fd5b506200003262000026620000dc60201b60201c565b620000e460201b60201c565b620000667f39bbaedb82e6743a336be557192fb64c205b1c7023985a2169da77cfa38456e760001b620001a860201b60201c565b6200009a7f24db5b5cfdf4200d735f11046f2ae1a70f4558a5d72f76885640a569c06c07cf60001b620001a860201b60201c565b620000ce7f317e8430390de1cd59d658f9aa2e38e3fc3ede461a2882fce72bce93ad4b116360001b620001a860201b60201c565b6000600181905550620001ab565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b50565b6116cc80620001bb6000396000f3fe6080604052600436106100705760003560e01c80638da5cb5b1161004e5780638da5cb5b146100ce578063a0adbb93146100f9578063ad48144d14610122578063f2fde38b1461013e57610070565b806325999e7f146100755780635fd8c710146100a0578063715018a6146100b7575b600080fd5b34801561008157600080fd5b5061008a610167565b60405161009791906110ac565b60405180910390f35b3480156100ac57600080fd5b506100b561016d565b005b3480156100c357600080fd5b506100cc61041f565b005b3480156100da57600080fd5b506100e36104a7565b6040516100f09190611108565b60405180910390f35b34801561010557600080fd5b50610120600480360381019061011b9190611163565b6104d0565b005b61013c60048036038101906101379190611221565b6104d3565b005b34801561014a57600080fd5b50610165600480360381019061016091906112ad565b610ecf565b005b60015481565b610175610fc7565b73ffffffffffffffffffffffffffffffffffffffff166101936104a7565b73ffffffffffffffffffffffffffffffffffffffff16146101e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101e090611337565b60405180910390fd5b6102157ffe92f91ad70fcc788c91b5c6377091fddb1bb4643da297f26117462bd94f49fd60001b6104d0565b6102417f1703157428668d098e51859c561d5296ef183d7c69ae701c20e674a9fb1fc99d60001b6104d0565b61026d7fa3bdcd2326103ecf302266dfd6c4af18da60b0396e4465dbc816f02baf137a4d60001b6104d0565b60006102776104a7565b90506102a57fbcfc6ad7959841cabcf36b03dfcd357d7d622acca2ba6e9a43b2372593a2b1f460001b6104d0565b6102d17f627056f9061efb209e979f60571640480c8dc859fd3b1446b24f901abd471d7860001b6104d0565b60004790506103027f872f745d610a98fff77a703564a28bce54c15938fd721d2bb1c1c96b29f02cc060001b6104d0565b61032e7fc7b520880199ff8ecee4cb60a0f2910d8beafd85c2a5d75e88cd45146cbd88c860001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff167fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f18260405161037491906110ac565b60405180910390a26103a87fbb13c854fee71d4d649f60251494946a1dc47696ecdbc5239eebd0f0e09dedb660001b6104d0565b6103d47f848adaf7559bcfbc99734e73f7109730b5e7d6c9dac716b49e5293cd159045da60001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561041a573d6000803e3d6000fd5b505050565b610427610fc7565b73ffffffffffffffffffffffffffffffffffffffff166104456104a7565b73ffffffffffffffffffffffffffffffffffffffff161461049b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049290611337565b60405180910390fd5b6104a56000610fcf565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b50565b6104db610fc7565b73ffffffffffffffffffffffffffffffffffffffff166104f96104a7565b73ffffffffffffffffffffffffffffffffffffffff161461054f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161054690611337565b60405180910390fd5b61057b7f2ada5d99a5213ee4ca2bb15d1f40a59e356e720b5882c0781678a5e06b9ddb5960001b6104d0565b6105a77f7a7334b1d6bfe4bd15a6309ce921c6474f6768575c5e38d2b2ce7acc447ba59160001b6104d0565b6105d37fb807ae02c58a5c6be11b494711fb222a14e0d7e215117e68acdd94a81151ba7460001b6104d0565b60008282905090506106077f21ab292895678d1873f05582fb6da03baffcd8dbbf67acb7d05adbe92e38f27360001b6104d0565b6106337f807737600e915e0ac1bda9d244b1b42f3883b11d61a3714e96412ab37d49aa0d60001b6104d0565b61065f7fc1dafb9e03ad5f719e2b448b24a8dec5f2278a2d3a090d11212eccbf65b3b9dc60001b6104d0565b600081116106a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610699906113a3565b60405180910390fd5b6106ce7f23dbf8b6555265ebf2ff79777f7ef74ba63f296fc3b5440ee3f186724f49d63d60001b6104d0565b6106fa7f0f09cdc510c9eeadb6f4ffed3990e7ce53a93e2d1026c772e2303eb967ae645660001b6104d0565b6107267f442b40ff3f756dfe83209f66d82504cceb390151b2ea76b7ce2bce481ddb3b0e60001b6104d0565b600060015490506107597fb14a4d7d74c1e2df0ad5d1ac6189bd833e51ed69416aa7c504d01606d755c7ef60001b6104d0565b6107857f1338effe85e1ba3bde809611b8cd8ff762211afaccab634e6b6449395abbd82260001b6104d0565b6107b17fc20c000c8553b2152a7a80ac43c52f1b7ba7cbd04b533472fc0fd7fd7057f68060001b6104d0565b8481146107f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ea9061140f565b60405180910390fd5b61081f7fb25de3d3bad93e8f821dbd0a8d2aeb60bfa371bf7f2593187e3d6f3012cbbd1360001b6104d0565b61084b7fc1437f73ab0f757f501060cc8e214fb6e895e2c11fdec90f1c26c337259cb3b260001b6104d0565b816001600082825401925050819055506108877f60fb755f4c85c0f5e4fc55a59a862d71795ee75dd9aebd26397347a776a4438060001b6104d0565b6108b37f961eebfc60945127454266e3a2aa59e195e493c917f20887f27522f65f6138f360001b6104d0565b60006108e17f4a4656352b6110f616892179a43a4db2d257323981851d33e20f1d032afa810160001b6104d0565b61090d7f03453438aaa639cf92f4b9a0819dd07143a378d1d08840fd1091d6142cbd37ea60001b6104d0565b60005b838110156109ad576109447fa06b97308620cba29f8f5270af06b6b2b47882e99ef6a3ab7cb6ae3dff36e6c760001b6104d0565b6109707f1def478f38c0910e76e6a9de11aea3e47f48c79346e34413455d16858a227f7460001b6104d0565b8585828181106109835761098261142f565b5b9050604002016000013582610998919061148d565b915080806109a5906114e3565b915050610910565b506109da7f1bd35d5e9c2fadd60189746ebf51278308a09575bc3dacb8a2ce127511f4bd5b60001b6104d0565b610a067f6ed34bb8ab9df4b9f1295d0d512d642d3757c3c47b131b126385d8539862347060001b6104d0565b610a327f6140d5c902a63db76a3285429152fb3a87752f7db4120de3c9d932f328bc305060001b6104d0565b348114610a74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6b9061159e565b60405180910390fd5b610aa07f18246eeaf0026a3e2c4ac32cbc1dc0606e82d2890a32165286e3d0a8c95fd7a460001b6104d0565b610acc7f70b83d9371755905523d6f1e944a8b8692c0959960315ee55559fafd7c2c52bf60001b6104d0565b610af87f21baa28c2eb7d3242d4afa89ad217acdeea738ab84a007f3e8aa489d3ce867c860001b6104d0565b60005b83811015610ec657610b2f7fcdf5d58952d1caa81fdfa362bb2eeb66956f151aa2b33f407f9833563b20496e60001b6104d0565b610b5b7f82fdec1cc8aa1098d9a8242384eaea39f90e5593c12b39cb109348a772e9fafe60001b6104d0565b6000868683818110610b7057610b6f61142f565b5b905060400201600001359050610ba87faaf73602f455fb6fc88332cf7f6d0caabacde6b54d461dc6eb9a7ee12bb2b57460001b6104d0565b610bd47f0d14c42168fe96cb818965cb522ed1023d13f8dc0ab098cdf8760c35932c9cdf60001b6104d0565b6000878784818110610be957610be861142f565b5b9050604002016020016020810190610c0191906112ad565b9050610c2f7f4fccbbc284abd163c3c18f168872dc29d4fac77f01fc1cf5f9992b361605dc4f60001b6104d0565b610c5b7f14f24022c2530a4720a223a36c798ed655b1320c21a7fb1cd078146c936b277060001b6104d0565b60008173ffffffffffffffffffffffffffffffffffffffff16836108fc90604051610c85906115ef565b600060405180830381858888f193505050503d8060008114610cc3576040519150601f19603f3d011682016040523d82523d6000602084013e610cc8565b606091505b50509050610cf87f990d01d9292bbf5a72b844d9e480c435f5bf3f28c6a3cf01231653128d574a2960001b6104d0565b610d247fbeb05d1cb9e0c8962b3fbce755095395f809190d1f56a0305f52d745ed2be60860001b6104d0565b8015610dd657610d567f926cdb8fa3eec76098df0921133fbad388217c8a5f07adf0e3652e64344ff66760001b6104d0565b610d827fcf258c3a8696678566a6fd532ee096e27d2a9dc64bcc87d8fccf2c9df406855560001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff16867feaa22fd2d7b875476355b32cf719794faf9d91b66e73bc6375a053cace9caaee85604051610dc991906110ac565b60405180910390a3610e7e565b610e027f9065e1e3bc2a1b35f85ca394361800750d7ccf66381f3e69fe4faefe0e5cc78f60001b6104d0565b610e2e7f57081b0378c1c31ae18ff29ec060b75a2fcf8bec375989be94d0d303a4f0021160001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff16867f9b478c095979d3d3a7d602ffd9ee1f0843204d853558ae0882c8fcc0a5bc78cf85604051610e7591906110ac565b60405180910390a35b610eaa7f9de3918864af83d66c46c014e27703f1021307042aef5dcf52b75516706ddd8b60001b6104d0565b6001860195505050508080610ebe906114e3565b915050610afb565b50505050505050565b610ed7610fc7565b73ffffffffffffffffffffffffffffffffffffffff16610ef56104a7565b73ffffffffffffffffffffffffffffffffffffffff1614610f4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4290611337565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610fbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb290611676565b60405180910390fd5b610fc481610fcf565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6110a681611093565b82525050565b60006020820190506110c1600083018461109d565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006110f2826110c7565b9050919050565b611102816110e7565b82525050565b600060208201905061111d60008301846110f9565b92915050565b600080fd5b600080fd5b6000819050919050565b6111408161112d565b811461114b57600080fd5b50565b60008135905061115d81611137565b92915050565b60006020828403121561117957611178611123565b5b60006111878482850161114e565b91505092915050565b61119981611093565b81146111a457600080fd5b50565b6000813590506111b681611190565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111e1576111e06111bc565b5b8235905067ffffffffffffffff8111156111fe576111fd6111c1565b5b60208301915083604082028301111561121a576112196111c6565b5b9250929050565b60008060006040848603121561123a57611239611123565b5b6000611248868287016111a7565b935050602084013567ffffffffffffffff81111561126957611268611128565b5b611275868287016111cb565b92509250509250925092565b61128a816110e7565b811461129557600080fd5b50565b6000813590506112a781611281565b92915050565b6000602082840312156112c3576112c2611123565b5b60006112d184828501611298565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006113216020836112da565b915061132c826112eb565b602082019050919050565b6000602082019050818103600083015261135081611314565b9050919050565b7f4e6f2064697362757273656d656e747300000000000000000000000000000000600082015250565b600061138d6010836112da565b915061139882611357565b602082019050919050565b600060208201905081810360008301526113bc81611380565b9050919050565b7f556e6578706563746564206e657874206465706f736974206964000000000000600082015250565b60006113f9601a836112da565b9150611404826113c3565b602082019050919050565b60006020820190508181036000830152611428816113ec565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061149882611093565b91506114a383611093565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156114d8576114d761145e565b5b828201905092915050565b60006114ee82611093565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156115215761152061145e565b5b600182019050919050565b7f44697362757273656d656e7420746f74616c20213d20616d6f756e742073656e60008201527f7400000000000000000000000000000000000000000000000000000000000000602082015250565b60006115886021836112da565b91506115938261152c565b604082019050919050565b600060208201905081810360008301526115b78161157b565b9050919050565b600081905092915050565b50565b60006115d96000836115be565b91506115e4826115c9565b600082019050919050565b60006115fa826115cc565b9150819050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006116606026836112da565b915061166b82611604565b604082019050919050565b6000602082019050818103600083015261168f81611653565b905091905056fea264697066735822122083f16098b83d1bcd3c8f88b64cd62c2ff0f7149c4df36e3ea3404931581a899064736f6c63430008090033",
"deployedBytecode": "0x6080604052600436106100705760003560e01c80638da5cb5b1161004e5780638da5cb5b146100ce578063a0adbb93146100f9578063ad48144d14610122578063f2fde38b1461013e57610070565b806325999e7f146100755780635fd8c710146100a0578063715018a6146100b7575b600080fd5b34801561008157600080fd5b5061008a610167565b60405161009791906110ac565b60405180910390f35b3480156100ac57600080fd5b506100b561016d565b005b3480156100c357600080fd5b506100cc61041f565b005b3480156100da57600080fd5b506100e36104a7565b6040516100f09190611108565b60405180910390f35b34801561010557600080fd5b50610120600480360381019061011b9190611163565b6104d0565b005b61013c60048036038101906101379190611221565b6104d3565b005b34801561014a57600080fd5b50610165600480360381019061016091906112ad565b610ecf565b005b60015481565b610175610fc7565b73ffffffffffffffffffffffffffffffffffffffff166101936104a7565b73ffffffffffffffffffffffffffffffffffffffff16146101e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101e090611337565b60405180910390fd5b6102157ffe92f91ad70fcc788c91b5c6377091fddb1bb4643da297f26117462bd94f49fd60001b6104d0565b6102417f1703157428668d098e51859c561d5296ef183d7c69ae701c20e674a9fb1fc99d60001b6104d0565b61026d7fa3bdcd2326103ecf302266dfd6c4af18da60b0396e4465dbc816f02baf137a4d60001b6104d0565b60006102776104a7565b90506102a57fbcfc6ad7959841cabcf36b03dfcd357d7d622acca2ba6e9a43b2372593a2b1f460001b6104d0565b6102d17f627056f9061efb209e979f60571640480c8dc859fd3b1446b24f901abd471d7860001b6104d0565b60004790506103027f872f745d610a98fff77a703564a28bce54c15938fd721d2bb1c1c96b29f02cc060001b6104d0565b61032e7fc7b520880199ff8ecee4cb60a0f2910d8beafd85c2a5d75e88cd45146cbd88c860001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff167fddc398b321237a8d40ac914388309c2f52a08c134e4dc4ce61e32f57cb7d80f18260405161037491906110ac565b60405180910390a26103a87fbb13c854fee71d4d649f60251494946a1dc47696ecdbc5239eebd0f0e09dedb660001b6104d0565b6103d47f848adaf7559bcfbc99734e73f7109730b5e7d6c9dac716b49e5293cd159045da60001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561041a573d6000803e3d6000fd5b505050565b610427610fc7565b73ffffffffffffffffffffffffffffffffffffffff166104456104a7565b73ffffffffffffffffffffffffffffffffffffffff161461049b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161049290611337565b60405180910390fd5b6104a56000610fcf565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b50565b6104db610fc7565b73ffffffffffffffffffffffffffffffffffffffff166104f96104a7565b73ffffffffffffffffffffffffffffffffffffffff161461054f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161054690611337565b60405180910390fd5b61057b7f2ada5d99a5213ee4ca2bb15d1f40a59e356e720b5882c0781678a5e06b9ddb5960001b6104d0565b6105a77f7a7334b1d6bfe4bd15a6309ce921c6474f6768575c5e38d2b2ce7acc447ba59160001b6104d0565b6105d37fb807ae02c58a5c6be11b494711fb222a14e0d7e215117e68acdd94a81151ba7460001b6104d0565b60008282905090506106077f21ab292895678d1873f05582fb6da03baffcd8dbbf67acb7d05adbe92e38f27360001b6104d0565b6106337f807737600e915e0ac1bda9d244b1b42f3883b11d61a3714e96412ab37d49aa0d60001b6104d0565b61065f7fc1dafb9e03ad5f719e2b448b24a8dec5f2278a2d3a090d11212eccbf65b3b9dc60001b6104d0565b600081116106a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610699906113a3565b60405180910390fd5b6106ce7f23dbf8b6555265ebf2ff79777f7ef74ba63f296fc3b5440ee3f186724f49d63d60001b6104d0565b6106fa7f0f09cdc510c9eeadb6f4ffed3990e7ce53a93e2d1026c772e2303eb967ae645660001b6104d0565b6107267f442b40ff3f756dfe83209f66d82504cceb390151b2ea76b7ce2bce481ddb3b0e60001b6104d0565b600060015490506107597fb14a4d7d74c1e2df0ad5d1ac6189bd833e51ed69416aa7c504d01606d755c7ef60001b6104d0565b6107857f1338effe85e1ba3bde809611b8cd8ff762211afaccab634e6b6449395abbd82260001b6104d0565b6107b17fc20c000c8553b2152a7a80ac43c52f1b7ba7cbd04b533472fc0fd7fd7057f68060001b6104d0565b8481146107f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ea9061140f565b60405180910390fd5b61081f7fb25de3d3bad93e8f821dbd0a8d2aeb60bfa371bf7f2593187e3d6f3012cbbd1360001b6104d0565b61084b7fc1437f73ab0f757f501060cc8e214fb6e895e2c11fdec90f1c26c337259cb3b260001b6104d0565b816001600082825401925050819055506108877f60fb755f4c85c0f5e4fc55a59a862d71795ee75dd9aebd26397347a776a4438060001b6104d0565b6108b37f961eebfc60945127454266e3a2aa59e195e493c917f20887f27522f65f6138f360001b6104d0565b60006108e17f4a4656352b6110f616892179a43a4db2d257323981851d33e20f1d032afa810160001b6104d0565b61090d7f03453438aaa639cf92f4b9a0819dd07143a378d1d08840fd1091d6142cbd37ea60001b6104d0565b60005b838110156109ad576109447fa06b97308620cba29f8f5270af06b6b2b47882e99ef6a3ab7cb6ae3dff36e6c760001b6104d0565b6109707f1def478f38c0910e76e6a9de11aea3e47f48c79346e34413455d16858a227f7460001b6104d0565b8585828181106109835761098261142f565b5b9050604002016000013582610998919061148d565b915080806109a5906114e3565b915050610910565b506109da7f1bd35d5e9c2fadd60189746ebf51278308a09575bc3dacb8a2ce127511f4bd5b60001b6104d0565b610a067f6ed34bb8ab9df4b9f1295d0d512d642d3757c3c47b131b126385d8539862347060001b6104d0565b610a327f6140d5c902a63db76a3285429152fb3a87752f7db4120de3c9d932f328bc305060001b6104d0565b348114610a74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6b9061159e565b60405180910390fd5b610aa07f18246eeaf0026a3e2c4ac32cbc1dc0606e82d2890a32165286e3d0a8c95fd7a460001b6104d0565b610acc7f70b83d9371755905523d6f1e944a8b8692c0959960315ee55559fafd7c2c52bf60001b6104d0565b610af87f21baa28c2eb7d3242d4afa89ad217acdeea738ab84a007f3e8aa489d3ce867c860001b6104d0565b60005b83811015610ec657610b2f7fcdf5d58952d1caa81fdfa362bb2eeb66956f151aa2b33f407f9833563b20496e60001b6104d0565b610b5b7f82fdec1cc8aa1098d9a8242384eaea39f90e5593c12b39cb109348a772e9fafe60001b6104d0565b6000868683818110610b7057610b6f61142f565b5b905060400201600001359050610ba87faaf73602f455fb6fc88332cf7f6d0caabacde6b54d461dc6eb9a7ee12bb2b57460001b6104d0565b610bd47f0d14c42168fe96cb818965cb522ed1023d13f8dc0ab098cdf8760c35932c9cdf60001b6104d0565b6000878784818110610be957610be861142f565b5b9050604002016020016020810190610c0191906112ad565b9050610c2f7f4fccbbc284abd163c3c18f168872dc29d4fac77f01fc1cf5f9992b361605dc4f60001b6104d0565b610c5b7f14f24022c2530a4720a223a36c798ed655b1320c21a7fb1cd078146c936b277060001b6104d0565b60008173ffffffffffffffffffffffffffffffffffffffff16836108fc90604051610c85906115ef565b600060405180830381858888f193505050503d8060008114610cc3576040519150601f19603f3d011682016040523d82523d6000602084013e610cc8565b606091505b50509050610cf87f990d01d9292bbf5a72b844d9e480c435f5bf3f28c6a3cf01231653128d574a2960001b6104d0565b610d247fbeb05d1cb9e0c8962b3fbce755095395f809190d1f56a0305f52d745ed2be60860001b6104d0565b8015610dd657610d567f926cdb8fa3eec76098df0921133fbad388217c8a5f07adf0e3652e64344ff66760001b6104d0565b610d827fcf258c3a8696678566a6fd532ee096e27d2a9dc64bcc87d8fccf2c9df406855560001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff16867feaa22fd2d7b875476355b32cf719794faf9d91b66e73bc6375a053cace9caaee85604051610dc991906110ac565b60405180910390a3610e7e565b610e027f9065e1e3bc2a1b35f85ca394361800750d7ccf66381f3e69fe4faefe0e5cc78f60001b6104d0565b610e2e7f57081b0378c1c31ae18ff29ec060b75a2fcf8bec375989be94d0d303a4f0021160001b6104d0565b8173ffffffffffffffffffffffffffffffffffffffff16867f9b478c095979d3d3a7d602ffd9ee1f0843204d853558ae0882c8fcc0a5bc78cf85604051610e7591906110ac565b60405180910390a35b610eaa7f9de3918864af83d66c46c014e27703f1021307042aef5dcf52b75516706ddd8b60001b6104d0565b6001860195505050508080610ebe906114e3565b915050610afb565b50505050505050565b610ed7610fc7565b73ffffffffffffffffffffffffffffffffffffffff16610ef56104a7565b73ffffffffffffffffffffffffffffffffffffffff1614610f4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4290611337565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610fbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb290611676565b60405180910390fd5b610fc481610fcf565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b6110a681611093565b82525050565b60006020820190506110c1600083018461109d565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006110f2826110c7565b9050919050565b611102816110e7565b82525050565b600060208201905061111d60008301846110f9565b92915050565b600080fd5b600080fd5b6000819050919050565b6111408161112d565b811461114b57600080fd5b50565b60008135905061115d81611137565b92915050565b60006020828403121561117957611178611123565b5b60006111878482850161114e565b91505092915050565b61119981611093565b81146111a457600080fd5b50565b6000813590506111b681611190565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111e1576111e06111bc565b5b8235905067ffffffffffffffff8111156111fe576111fd6111c1565b5b60208301915083604082028301111561121a576112196111c6565b5b9250929050565b60008060006040848603121561123a57611239611123565b5b6000611248868287016111a7565b935050602084013567ffffffffffffffff81111561126957611268611128565b5b611275868287016111cb565b92509250509250925092565b61128a816110e7565b811461129557600080fd5b50565b6000813590506112a781611281565b92915050565b6000602082840312156112c3576112c2611123565b5b60006112d184828501611298565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006113216020836112da565b915061132c826112eb565b602082019050919050565b6000602082019050818103600083015261135081611314565b9050919050565b7f4e6f2064697362757273656d656e747300000000000000000000000000000000600082015250565b600061138d6010836112da565b915061139882611357565b602082019050919050565b600060208201905081810360008301526113bc81611380565b9050919050565b7f556e6578706563746564206e657874206465706f736974206964000000000000600082015250565b60006113f9601a836112da565b9150611404826113c3565b602082019050919050565b60006020820190508181036000830152611428816113ec565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061149882611093565b91506114a383611093565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156114d8576114d761145e565b5b828201905092915050565b60006114ee82611093565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156115215761152061145e565b5b600182019050919050565b7f44697362757273656d656e7420746f74616c20213d20616d6f756e742073656e60008201527f7400000000000000000000000000000000000000000000000000000000000000602082015250565b60006115886021836112da565b91506115938261152c565b604082019050919050565b600060208201905081810360008301526115b78161157b565b9050919050565b600081905092915050565b50565b60006115d96000836115be565b91506115e4826115c9565b600082019050919050565b60006115fa826115cc565b9150819050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006116606026836112da565b915061166b82611604565b604082019050919050565b6000602082019050818103600083015261168f81611653565b905091905056fea264697066735822122083f16098b83d1bcd3c8f88b64cd62c2ff0f7149c4df36e3ea3404931581a899064736f6c63430008090033",
"devdoc": {
"events": {
"BalanceWithdrawn(address,uint256)": {
"params": {
"balance": "The current contract balance paid to the owner.",
"owner": "The current owner and recipient of the funds."
}
},
"DisbursementFailed(uint256,address,uint256)": {
"params": {
"amount": "The amount intended to be sent to the recipient.",
"depositId": "The unique sequence number identifying the deposit.",
"to": "The intended recipient of the disbursement."
}
},
"DisbursementSuccess(uint256,address,uint256)": {
"params": {
"amount": "The amount sent to the recipient.",
"depositId": "The unique sequence number identifying the deposit.",
"to": "The recipient of the disbursement."
}
}
},
"kind": "dev",
"methods": {
"disburse(uint256,(uint256,address)[])": {
"params": {
"_disbursements": "A list of Disbursements to process.",
"_nextDepositId": "The depositId of the first Dispursement."
}
},
"owner()": {
"details": "Returns the address of the current owner."
},
"renounceOwnership()": {
"details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."
},
"transferOwnership(address)": {
"details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
}
},
"title": "TeleportrDisburser",
"version": 1
},
"userdoc": {
"events": {
"BalanceWithdrawn(address,uint256)": {
"notice": "Emitted any time the balance is withdrawn by the owner."
},
"DisbursementFailed(uint256,address,uint256)": {
"notice": "Emitted any time a disbursement fails to send."
},
"DisbursementSuccess(uint256,address,uint256)": {
"notice": "Emitted any time a disbursement is successfuly sent."
}
},
"kind": "user",
"methods": {
"constructor": {
"notice": "Initializes a new TeleportrDisburser contract."
},
"disburse(uint256,(uint256,address)[])": {
"notice": "Accepts a list of Disbursements and forwards the amount paid to the contract to each recipient. The method reverts if there are zero disbursements, the total amount to forward differs from the amount sent in the transaction, or the _nextDepositId is unexpected. Failed disbursements will not cause the method to revert, but will instead be held by the contract and availabe for the owner to withdraw."
},
"totalDisbursements()": {
"notice": "The total number of disbursements processed."
},
"withdrawBalance()": {
"notice": "Sends the contract's current balance to the owner."
}
},
"version": 1
},
"storageLayout": {
"storage": [
{
"astId": 393,
"contract": "contracts/L2/teleportr/TeleportrDisburser.sol:TeleportrDisburser",
"label": "_owner",
"offset": 0,
"slot": "0",
"type": "t_address"
},
{
"astId": 10517,
"contract": "contracts/L2/teleportr/TeleportrDisburser.sol:TeleportrDisburser",
"label": "totalDisbursements",
"offset": 0,
"slot": "1",
"type": "t_uint256"
}
],
"types": {
"t_address": {
"encoding": "inplace",
"label": "address",
"numberOfBytes": "20"
},
"t_uint256": {
"encoding": "inplace",
"label": "uint256",
"numberOfBytes": "32"
}
}
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,7 @@ dotenv.config() ...@@ -23,6 +23,7 @@ dotenv.config()
const enableGasReport = !!process.env.ENABLE_GAS_REPORT const enableGasReport = !!process.env.ENABLE_GAS_REPORT
const privateKey = process.env.PRIVATE_KEY || '0x' + '11'.repeat(32) // this is to avoid hardhat error const privateKey = process.env.PRIVATE_KEY || '0x' + '11'.repeat(32) // this is to avoid hardhat error
const deploy = process.env.DEPLOY_DIRECTORY || 'deploy'
const config: HardhatUserConfig = { const config: HardhatUserConfig = {
networks: { networks: {
...@@ -40,11 +41,13 @@ const config: HardhatUserConfig = { ...@@ -40,11 +41,13 @@ const config: HardhatUserConfig = {
'optimism-kovan': { 'optimism-kovan': {
chainId: 69, chainId: 69,
url: 'https://kovan.optimism.io', url: 'https://kovan.optimism.io',
deploy,
accounts: [privateKey], accounts: [privateKey],
}, },
'optimism-mainnet': { 'optimism-mainnet': {
chainId: 10, chainId: 10,
url: 'https://mainnet.optimism.io', url: 'https://mainnet.optimism.io',
deploy,
accounts: [privateKey], accounts: [privateKey],
}, },
'mainnet-trial': { 'mainnet-trial': {
...@@ -52,6 +55,18 @@ const config: HardhatUserConfig = { ...@@ -52,6 +55,18 @@ const config: HardhatUserConfig = {
url: 'http://127.0.0.1:8545', url: 'http://127.0.0.1:8545',
accounts: [privateKey], accounts: [privateKey],
}, },
kovan: {
chainId: 42,
url: process.env.CONTRACTS_RPC_URL || '',
deploy,
accounts: [privateKey],
},
mainnet: {
chainId: 1,
url: process.env.CONTRACTS_RPC_URL || '',
deploy,
accounts: [privateKey],
},
}, },
mocha: { mocha: {
timeout: 50000, timeout: 50000,
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
"build": "yarn build:contracts && yarn autogen:artifacts && yarn build:typescript", "build": "yarn build:contracts && yarn autogen:artifacts && yarn build:typescript",
"build:typescript": "tsc -p ./tsconfig.build.json", "build:typescript": "tsc -p ./tsconfig.build.json",
"build:contracts": "hardhat compile --show-stack-traces", "build:contracts": "hardhat compile --show-stack-traces",
"build:dump": "ts-node bin/take-dump.ts",
"autogen:markdown": "ts-node scripts/generate-markdown.ts", "autogen:markdown": "ts-node scripts/generate-markdown.ts",
"autogen:artifacts": "ts-node scripts/generate-artifacts.ts && ts-node scripts/generate-deployed-artifacts.ts", "autogen:artifacts": "ts-node scripts/generate-artifacts.ts && ts-node scripts/generate-deployed-artifacts.ts",
"test": "yarn test:contracts", "test": "yarn test:contracts",
......
#!/bin/bash
export L2_BLOCK_GAS_LIMIT=15000000
export L2_CHAIN_ID=420
export BLOCK_SIGNER_ADDRESS=0x27770a9694e4B4b1E130Ab91Bc327C36855f612E
export L1_STANDARD_BRIDGE_ADDRESS=0x73298186A143a54c20ae98EEE5a025bD5979De02
export L1_FEE_WALLET_ADDRESS=0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244
export L1_CROSS_DOMAIN_MESSENGER_ADDRESS=0xEcC89b9EDD804850C4F343A278Be902be11AaF42
export WHITELIST_OWNER=0x0000000000000000000000000000000000000000
export GAS_PRICE_ORACLE_OWNER=0x84f70449f90300997840eCb0918873745Ede7aE6
yarn build:dump
#!/bin/bash
### DEPLOYMENT SCRIPT ###
# To be called from root of contracts dir #
# Required env vars
if [[ -z "$CONTRACTS_DEPLOYER_KEY" ]]; then
echo "Must pass CONTRACTS_DEPLOYER_KEY"
exit 1
fi
if [[ -z "$CONTRACTS_RPC_URL" ]]; then
echo "Must pass CONTRACTS_RPC_URL"
exit 1
fi
if [[ -z "$ETHERSCAN_API_KEY" ]]; then
echo "Must pass ETHERSCAN_API_KEY"
exit 1
fi
CONTRACTS_TARGET_NETWORK=goerli \
npx hardhat deploy \
--l1-block-time-seconds 15 \
--ctc-max-transaction-gas-limit 15000000 \
--ctc-l2-gas-discount-divisor 32 \
--ctc-enqueue-gas-cost 60000 \
--scc-fraud-proof-window 604800 \
--scc-sequencer-publish-window 12592000 \
--ovm-sequencer-address 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244 \
--ovm-proposer-address 0x9A2F243c605e6908D96b18e21Fb82Bf288B19EF3 \
--ovm-address-manager-owner 0x32b70c156302d28A9119445d2bbb9ab1cBD01671 \
--network goerli
CONTRACTS_TARGET_NETWORK=goerli \
npx hardhat etherscan-verify --network goerli
#!/bin/bash
export L2_BLOCK_GAS_LIMIT=15000000
export L2_CHAIN_ID=69
export BLOCK_SIGNER_ADDRESS=0x00000398232E2064F896018496b4b44b3D62751F
export L1_STANDARD_BRIDGE_ADDRESS=0x22F24361D548e5FaAfb36d1437839f080363982B
export L1_FEE_WALLET_ADDRESS=0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244
export L1_CROSS_DOMAIN_MESSENGER_ADDRESS=0x4361d0F75A0186C05f971c566dC6bEa5957483fD
export WHITELIST_OWNER=0x0000000000000000000000000000000000000000
export GAS_PRICE_ORACLE_OWNER=0x84f70449f90300997840eCb0918873745Ede7aE6
yarn build:dump
#!/bin/bash
### DEPLOYMENT SCRIPT ###
# To be called from root of contracts dir #
# Required env vars
if [[ -z "$CONTRACTS_DEPLOYER_KEY" ]]; then
echo "Must pass CONTRACTS_DEPLOYER_KEY"
exit 1
fi
if [[ -z "$CONTRACTS_RPC_URL" ]]; then
echo "Must pass CONTRACTS_RPC_URL"
exit 1
fi
if [[ -z "$ETHERSCAN_API_KEY" ]]; then
echo "Must pass ETHERSCAN_API_KEY"
exit 1
fi
CONTRACTS_TARGET_NETWORK=kovan \
npx hardhat deploy \
--l1-block-time-seconds 15 \
--ctc-max-transaction-gas-limit 15000000 \
--ctc-l2-gas-discount-divisor 32 \
--ctc-enqueue-gas-cost 60000 \
--scc-fraud-proof-window 10 \
--scc-sequencer-publish-window 12592000 \
--ovm-sequencer-address 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244 \
--ovm-proposer-address 0x9A2F243c605e6908D96b18e21Fb82Bf288B19EF3 \
--ovm-address-manager-owner 0x18394B52d3Cb931dfA76F63251919D051953413d \
--gasprice 1000000000 \
--num-deploy-confirmations 1 \
--tags upgrade \
--network kovan
CONTRACTS_TARGET_NETWORK=kovan \
npx hardhat etherscan-verify \
--network kovan \
--sleep
#!/bin/bash
export L2_BLOCK_GAS_LIMIT=15000000
export L2_CHAIN_ID=10
export BLOCK_SIGNER_ADDRESS=0x00000398232E2064F896018496b4b44b3D62751F
export L1_STANDARD_BRIDGE_ADDRESS=0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1
export L1_FEE_WALLET_ADDRESS=0x391716d440c151c42cdf1c95c1d83a5427bca52c
export L1_CROSS_DOMAIN_MESSENGER_ADDRESS=0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1
export WHITELIST_OWNER=0x648E3e8101BFaB7bf5997Bd007Fb473786019159
export GAS_PRICE_ORACLE_OWNER=0x7107142636C85c549690b1Aca12Bdb8052d26Ae6
yarn build:dump
#!/bin/bash
export L2_BLOCK_GAS_LIMIT=15000000
export L2_CHAIN_ID=66666
export BLOCK_SIGNER_ADDRESS=0x27770a9694e4B4b1E130Ab91Bc327C36855f612E
export L1_STANDARD_BRIDGE_ADDRESS=0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1
export L1_FEE_WALLET_ADDRESS=0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244
export L1_CROSS_DOMAIN_MESSENGER_ADDRESS=0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1
export WHITELIST_OWNER=0x0000000000000000000000000000000000000000
export GAS_PRICE_ORACLE_OWNER=0x84f70449f90300997840eCb0918873745Ede7aE6
yarn build:dump
#!/bin/bash
### DEPLOYMENT SCRIPT ###
# To be called from root of contracts dir #
# Required env vars
if [[ -z "$CONTRACTS_DEPLOYER_KEY" ]]; then
echo "Must pass CONTRACTS_DEPLOYER_KEY"
exit 1
fi
if [[ -z "$CONTRACTS_RPC_URL" ]]; then
echo "Must pass CONTRACTS_RPC_URL"
exit 1
fi
if [[ -z "$ETHERSCAN_API_KEY" ]]; then
echo "Must pass ETHERSCAN_API_KEY"
exit 1
fi
CONTRACTS_TARGET_NETWORK=mainnet-trial \
npx hardhat deploy \
--ctc-max-transaction-gas-limit 15000000 \
--ctc-enqueue-gas-cost 60000 \
--ctc-l2-gas-discount-divisor 32 \
--l1-block-time-seconds 15 \
--ovm-address-manager-owner 0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A \
--ovm-sequencer-address 0xB79f76EF2c5F0286176833E7B2eEe103b1CC3244 \
--ovm-proposer-address 0x9A2F243c605e6908D96b18e21Fb82Bf288B19EF3 \
--scc-fraud-proof-window 10 \
--scc-sequencer-publish-window 12592000 \
--network mainnet-trial \
--gasprice 2000000000000 \
--forked true \
--num-deploy-confirmations 0 \
--tags upgrade
#!/bin/bash
### DEPLOYMENT SCRIPT ###
# To be called from root of contracts dir #
# Required env vars
if [[ -z "$CONTRACTS_DEPLOYER_KEY" ]]; then
echo "Must pass CONTRACTS_DEPLOYER_KEY"
exit 1
fi
if [[ -z "$CONTRACTS_RPC_URL" ]]; then
echo "Must pass CONTRACTS_RPC_URL"
exit 1
fi
if [[ -z "$ETHERSCAN_API_KEY" ]]; then
echo "Must pass ETHERSCAN_API_KEY"
exit 1
fi
CONTRACTS_TARGET_NETWORK=mainnet \
npx hardhat deploy \
--l1-block-time-seconds 15 \
--ctc-max-transaction-gas-limit 15000000 \
--ctc-l2-gas-discount-divisor 32 \
--ctc-enqueue-gas-cost 60000 \
--scc-fraud-proof-window 604800 \
--scc-sequencer-publish-window 12592000 \
--ovm-sequencer-address 0x6887246668a3b87F54DeB3b94Ba47a6f63F32985 \
--ovm-proposer-address 0x473300df21D047806A082244b417f96b32f13A33 \
--ovm-address-manager-owner 0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A \
--gasprice 150000000000 \
--num-deploy-confirmations 4 \
--tags upgrade \
--network mainnet
CONTRACTS_TARGET_NETWORK=mainnet \
npx hardhat etherscan-verify \
--network mainnet \
--sleep
import { ethers } from 'ethers'
/**
* Defines the configuration for a deployment.
*/
export interface DeployConfig {
/**
* Name of the network to deploy to. Must be the name of one of the networks listed in
* hardhat.config.ts.
*/
network: string
/**
* Whether or not this network is a forked network.
*/
isForkedNetwork?: boolean
/**
* Optional number of confs to wait during deployment.
*/
numDeployConfirmations?: number
/**
* Optional gas price to use for deployment transactions.
*/
gasPrice?: number
/**
* Estimated average L1 block time in seconds.
*/
l1BlockTimeSeconds: number
/**
* Gas limit for blocks on L2.
*/
l2BlockGasLimit: number
/**
* Chain ID for the L2 network.
*/
l2ChainId: number
/**
* Discount divisor used to calculate gas burn for L1 to L2 transactions.
*/
ctcL2GasDiscountDivisor: number
/**
* Cost of the "enqueue" function in the CTC.
*/
ctcEnqueueGasCost: number
/**
* Fault proof window in seconds.
*/
sccFaultProofWindowSeconds: number
/**
* Sequencer publish window in seconds.
*/
sccSequencerPublishWindowSeconds: number
/**
* Address of the Sequencer (publishes to CTC).
*/
ovmSequencerAddress: string
/**
* Address of the Proposer (publishes to SCC).
*/
ovmProposerAddress: string
/**
* Address of the account that will sign blocks.
*/
ovmBlockSignerAddress: string
/**
* Address that will receive fees on L1.
*/
ovmFeeWalletAddress: string
/**
* Address of the owner of the AddressManager contract on L1.
*/
ovmAddressManagerOwner: string
/**
* Address of the owner of the GasPriceOracle contract on L2.
*/
ovmGasPriceOracleOwner: string
/**
* Optional whitelist owner address.
*/
ovmWhitelistOwner?: string
/**
* Optional initial overhead value for GPO (default: 2750).
*/
gasPriceOracleOverhead?: number
/**
* Optional initial scalar value for GPO (default: 1500000).
*/
gasPriceOracleScalar?: number
/**
* Optional initial decimals for GPO (default: 6).
*/
gasPriceOracleDecimals?: number
/**
* Optional initial L1 base fee for GPO (default: 1).
*/
gasPriceOracleL1BaseFee?: number
/**
* Optional initial L2 gas price for GPO (default: 1).
*/
gasPriceOracleL2GasPrice?: number
/**
* Optional block number to enable the Berlin hardfork (default: 0).
*/
hfBerlinBlock?: number
}
/**
* Specification for each of the configuration options.
*/
const configSpec: {
[K in keyof DeployConfig]: {
type: string
default?: any
}
} = {
network: {
type: 'string',
},
isForkedNetwork: {
type: 'boolean',
default: false,
},
numDeployConfirmations: {
type: 'number',
default: 0,
},
gasPrice: {
type: 'number',
default: undefined,
},
l1BlockTimeSeconds: {
type: 'number',
},
l2BlockGasLimit: {
type: 'number',
},
l2ChainId: {
type: 'number',
},
ctcL2GasDiscountDivisor: {
type: 'number',
},
ctcEnqueueGasCost: {
type: 'number',
},
sccFaultProofWindowSeconds: {
type: 'number',
},
sccSequencerPublishWindowSeconds: {
type: 'number',
},
ovmSequencerAddress: {
type: 'address',
},
ovmProposerAddress: {
type: 'address',
},
ovmBlockSignerAddress: {
type: 'address',
},
ovmFeeWalletAddress: {
type: 'address',
},
ovmAddressManagerOwner: {
type: 'address',
},
ovmGasPriceOracleOwner: {
type: 'address',
},
ovmWhitelistOwner: {
type: 'address',
default: ethers.constants.AddressZero,
},
gasPriceOracleOverhead: {
type: 'number',
default: 2750,
},
gasPriceOracleScalar: {
type: 'number',
default: 1_500_000,
},
gasPriceOracleDecimals: {
type: 'number',
default: 6,
},
gasPriceOracleL1BaseFee: {
type: 'number',
default: 1,
},
gasPriceOracleL2GasPrice: {
type: 'number',
default: 1,
},
hfBerlinBlock: {
type: 'number',
default: 0,
},
}
/**
* Gets the deploy config for the given network.
*
* @param network Network name.
* @returns Deploy config for the given network.
*/
export const getDeployConfig = (network: string): Required<DeployConfig> => {
let config: DeployConfig
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
config = require(`../deploy-config/${network}.ts`).default
} catch (err) {
throw new Error(
`error while loading deploy config for network: ${network}, ${err}`
)
}
return parseDeployConfig(config)
}
/**
* Parses and validates the given deploy config, replacing any missing values with defaults.
*
* @param config Deploy config to parse.
* @returns Parsed deploy config.
*/
export const parseDeployConfig = (
config: DeployConfig
): Required<DeployConfig> => {
// Create a clone of the config object. Shallow clone is fine because none of the input options
// are expected to be objects or functions etc.
const parsed = { ...config }
for (const [key, spec] of Object.entries(configSpec)) {
// Make sure the value is defined, or use a default.
if (parsed[key] === undefined) {
if ('default' in spec) {
parsed[key] = spec.default
} else {
throw new Error(
`deploy config is missing required field: ${key} (${spec.type})`
)
}
} else {
// Make sure the default has the correct type.
if (spec.type === 'address') {
if (!ethers.utils.isAddress(parsed[key])) {
throw new Error(
`deploy config field: ${key} is not of type ${spec.type}: ${parsed[key]}`
)
}
} else if (typeof parsed[key] !== spec.type) {
throw new Error(
`deploy config field: ${key} is not of type ${spec.type}: ${parsed[key]}`
)
}
}
}
return parsed as Required<DeployConfig>
}
/* Imports: External */
import { ethers, Contract } from 'ethers' import { ethers, Contract } from 'ethers'
import { Provider } from '@ethersproject/abstract-provider' import { Provider } from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer' import { Signer } from '@ethersproject/abstract-signer'
import { sleep, awaitCondition } from '@eth-optimism/core-utils' import { sleep, awaitCondition } from '@eth-optimism/core-utils'
import { HttpNetworkConfig } from 'hardhat/types' import { HttpNetworkConfig } from 'hardhat/types'
import { getDeployConfig } from './deploy-config'
/** /**
* @param {Any} hre Hardhat runtime environment * @param {Any} hre Hardhat runtime environment
* @param {String} name Contract name from the names object * @param {String} name Contract name from the names object
...@@ -31,13 +32,14 @@ export const deployAndVerifyAndThen = async ({ ...@@ -31,13 +32,14 @@ export const deployAndVerifyAndThen = async ({
}) => { }) => {
const { deploy } = hre.deployments const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
const deployConfig = getDeployConfig(hre.network.name)
const result = await deploy(name, { const result = await deploy(name, {
contract, contract,
from: deployer, from: deployer,
args, args,
log: true, log: true,
waitConfirmations: hre.deployConfig.numDeployConfirmations, waitConfirmations: deployConfig.numDeployConfirmations,
}) })
await hre.ethers.provider.waitForTransaction(result.transactionHash) await hre.ethers.provider.waitForTransaction(result.transactionHash)
...@@ -92,6 +94,8 @@ export const getAdvancedContract = (opts: { ...@@ -92,6 +94,8 @@ export const getAdvancedContract = (opts: {
hre: any hre: any
contract: Contract contract: Contract
}): Contract => { }): Contract => {
const deployConfig = getDeployConfig(opts.hre.network.name)
// Temporarily override Object.defineProperty to bypass ether's object protection. // Temporarily override Object.defineProperty to bypass ether's object protection.
const def = Object.defineProperty const def = Object.defineProperty
Object.defineProperty = (obj, propName, prop) => { Object.defineProperty = (obj, propName, prop) => {
...@@ -115,7 +119,7 @@ export const getAdvancedContract = (opts: { ...@@ -115,7 +119,7 @@ export const getAdvancedContract = (opts: {
// We want to use the gas price that has been configured at the beginning of the deployment. // We want to use the gas price that has been configured at the beginning of the deployment.
// However, if the function being triggered is a "constant" (static) function, then we don't // However, if the function being triggered is a "constant" (static) function, then we don't
// want to provide a gas price because we're prone to getting insufficient balance errors. // want to provide a gas price because we're prone to getting insufficient balance errors.
let gasPrice = opts.hre.deployConfig.gasPrice || undefined let gasPrice = deployConfig.gasPrice || undefined
if (contract.interface.getFunction(fnName).constant) { if (contract.interface.getFunction(fnName).constant) {
gasPrice = 0 gasPrice = 0
} }
...@@ -147,7 +151,7 @@ export const getAdvancedContract = (opts: { ...@@ -147,7 +151,7 @@ export const getAdvancedContract = (opts: {
return contract[fnName](...args) return contract[fnName](...args)
} }
} else if ( } else if (
receipt.confirmations >= opts.hre.deployConfig.numDeployConfirmations receipt.confirmations >= deployConfig.numDeployConfirmations
) { ) {
return tx return tx
} }
...@@ -163,7 +167,9 @@ export const fundAccount = async ( ...@@ -163,7 +167,9 @@ export const fundAccount = async (
address: string, address: string,
amount: ethers.BigNumber amount: ethers.BigNumber
) => { ) => {
if ((hre as any).deployConfig.forked !== 'true') { const deployConfig = getDeployConfig(hre.network.name)
if (!deployConfig.isForkedNetwork) {
throw new Error('this method can only be used against a forked network') throw new Error('this method can only be used against a forked network')
} }
...@@ -194,7 +200,9 @@ export const sendImpersonatedTx = async (opts: { ...@@ -194,7 +200,9 @@ export const sendImpersonatedTx = async (opts: {
gas: string gas: string
args: any[] args: any[]
}) => { }) => {
if ((opts.hre as any).deployConfig.forked !== 'true') { const deployConfig = getDeployConfig(opts.hre.network.name)
if (!deployConfig.isForkedNetwork) {
throw new Error('this method can only be used against a forked network') throw new Error('this method can only be used against a forked network')
} }
......
/* Imports: External */
import { ethers } from 'ethers'
import { task } from 'hardhat/config'
import * as types from 'hardhat/internal/core/params/argumentTypes'
task('deploy-teleportr-l1')
.addParam(
'minDepositAmountEth',
'Minimum deposit amount, in ETH.',
undefined,
types.string
)
.addParam(
'maxDepositAmountEth',
'Maximum deposit amount, in ETH.',
undefined,
types.string
)
.addParam(
'maxBalanceEth',
'Maximum contract balance, in ETH.',
undefined,
types.string
)
.addOptionalParam(
'numDeployConfirmations',
'Number of confirmations to wait for each transaction in the deployment. More is safer.',
1,
types.int
)
.setAction(
async (
{
minDepositAmountEth,
maxDepositAmountEth,
maxBalanceEth,
numDeployConfirmations,
},
hre: any
) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
console.log('Deploying TeleportrDeposit... ')
await deploy('TeleportrDeposit', {
from: deployer,
args: [
ethers.utils.parseEther(minDepositAmountEth),
ethers.utils.parseEther(maxDepositAmountEth),
ethers.utils.parseEther(maxBalanceEth),
],
log: true,
waitConfirmations: numDeployConfirmations,
})
console.log('Done.')
}
)
task('deploy-teleportr-l2').setAction(
async ({ numDeployConfirmations }, hre: any) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
console.log('Deploying TeleportrDisburser... ')
await deploy('TeleportrDisburser', {
from: deployer,
args: [],
log: true,
waitConfirmations: numDeployConfirmations,
})
console.log('Done.')
}
)
/* Imports: External */
import { ethers } from 'ethers'
import { task } from 'hardhat/config'
import * as types from 'hardhat/internal/core/params/argumentTypes'
const DEFAULT_L1_BLOCK_TIME_SECONDS = 15
const DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT = 11_000_000
const DEFAULT_CTC_L2_GAS_DISCOUNT_DIVISOR = 32
const DEFAULT_CTC_ENQUEUE_GAS_COST = 60_000
const DEFAULT_SCC_FRAUD_PROOF_WINDOW = 60 * 60 * 24 * 7 // 7 days
const DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW = 60 * 30 // 30 minutes
const DEFAULT_DEPLOY_CONFIRMATIONS = 12
task('deploy')
// Rollup config options
.addOptionalParam(
'l1BlockTimeSeconds',
'Number of seconds on average between every L1 block.',
DEFAULT_L1_BLOCK_TIME_SECONDS,
types.int
)
.addOptionalParam(
'ctcMaxTransactionGasLimit',
'Max gas limit for L1 queue transactions.',
DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT,
types.int
)
.addOptionalParam(
'ctcL2GasDiscountDivisor',
'Max gas limit for L1 queue transactions.',
DEFAULT_CTC_L2_GAS_DISCOUNT_DIVISOR,
types.int
)
.addOptionalParam(
'ctcEnqueueGasCost',
'Max gas limit for L1 queue transactions.',
DEFAULT_CTC_ENQUEUE_GAS_COST,
types.int
)
.addOptionalParam(
'sccFraudProofWindow',
'Number of seconds until a transaction is considered finalized.',
DEFAULT_SCC_FRAUD_PROOF_WINDOW,
types.int
)
.addOptionalParam(
'sccSequencerPublishWindow',
'Number of seconds that the sequencer is exclusively allowed to post state roots.',
DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW,
types.int
)
// Permissioned address options
.addOptionalParam(
'ovmSequencerAddress',
'Address of the sequencer. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'ovmProposerAddress',
'Address of the account that will propose state roots. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'ovmAddressManagerOwner',
'Address that will own the Lib_AddressManager. Must be provided or this deployment will fail.',
undefined,
types.string
)
.addOptionalParam(
'numDeployConfirmations',
'Number of confirmations to wait for each transaction in the deployment. More is safer.',
DEFAULT_DEPLOY_CONFIRMATIONS,
types.int
)
.addOptionalParam(
'forked',
'Enable this when using a forked network (use "true")',
undefined,
types.string
)
.setAction(async (args, hre: any, runSuper) => {
// Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks.
const validateAddressArg = (argName: string) => {
if (args[argName] === undefined) {
throw new Error(
`argument for ${argName} is required but was not provided`
)
}
if (!ethers.utils.isAddress(args[argName])) {
throw new Error(
`argument for ${argName} is not a valid address: ${args[argName]}`
)
}
}
validateAddressArg('ovmSequencerAddress')
validateAddressArg('ovmProposerAddress')
validateAddressArg('ovmAddressManagerOwner')
hre.deployConfig = args
return runSuper(args)
})
export * from './deploy'
export * from './l2-gasprice' export * from './l2-gasprice'
export * from './set-owner' export * from './set-owner'
export * from './take-dump'
export * from './validate-address-dictator' export * from './validate-address-dictator'
export * from './validate-chugsplash-dictator' export * from './validate-chugsplash-dictator'
export * from './whitelist' export * from './whitelist'
export * from './withdraw-fees' export * from './withdraw-fees'
export * from './fetch-batches' export * from './fetch-batches'
export * from './deploy-teleportr'
/* External Imports */ import * as path from 'path'
import * as fs from 'fs'
import { exec } from 'child_process' import { exec } from 'child_process'
import { promisify } from 'util' import { promisify } from 'util'
import * as mkdirp from 'mkdirp'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { import { task } from 'hardhat/config'
computeStorageSlots,
getStorageLayout,
} from '@defi-wonderland/smock/dist/src/utils'
import { remove0x } from '@eth-optimism/core-utils' import { remove0x } from '@eth-optimism/core-utils'
/* Internal Imports */ import { predeploys } from '../src/predeploys'
import { predeploys } from './predeploys' import { getContractFromArtifact } from '../src/deploy-utils'
import { getContractArtifact } from './contract-artifacts' import { getDeployConfig } from '../src/deploy-config'
import { names } from '../src/address-names'
export interface RollupDeployConfig {
// Address that will own the L2 deployer whitelist. task('take-dump').setAction(async (args, hre) => {
whitelistOwner: string /* eslint-disable @typescript-eslint/no-var-requires */
// Address that will own the L2 gas price oracle.
gasPriceOracleOwner: string // Needs to be imported here or hardhat will throw a fit about hardhat being imported from
// Overhead value of the gas price oracle // within the configuration file.
gasPriceOracleOverhead: number const {
// Scalar value of the gas price oracle computeStorageSlots,
gasPriceOracleScalar: number getStorageLayout,
// L1 base fee of the gas price oracle } = require('@defi-wonderland/smock/dist/src/utils')
gasPriceOracleL1BaseFee: number
// L2 gas price of the gas price oracle // Needs to be imported here because the artifacts can only be generated after the contracts have
gasPriceOracleGasPrice: number // been compiled, but compiling the contracts will import the config file which, as a result,
// Number of decimals of the gas price oracle scalar // will import this file.
gasPriceOracleDecimals: number const { getContractArtifact } = require('../src/contract-artifacts')
// Initial value for the L2 block gas limit.
l2BlockGasLimit: number /* eslint-enable @typescript-eslint/no-var-requires */
// Chain ID to give the L2 network.
l2ChainId: number // Make sure we have a deploy config for this network
// Address of the key that will sign blocks. const deployConfig = getDeployConfig(hre.network.name)
blockSignerAddress: string
// Address of the L1StandardBridge contract. // Basic warning so users know that the whitelist will be disabled if the owner is the zero address.
l1StandardBridgeAddress: string if (
// Address of the L1 fee wallet. deployConfig.ovmWhitelistOwner === undefined ||
l1FeeWalletAddress: string deployConfig.ovmWhitelistOwner === ethers.constants.AddressZero
// Address of the L1CrossDomainMessenger contract. ) {
l1CrossDomainMessengerAddress: string console.log(
// Block height to activate berlin hardfork 'WARNING: whitelist owner is undefined or address(0), whitelist will be disabled'
berlinBlock: number )
}
/**
* Generates the initial state for the L2 system by injecting the relevant L2 system contracts.
*
* @param cfg Configuration for the L2 system.
* @returns Generated L2 genesis state.
*/
export const makeL2GenesisFile = async (
cfg: RollupDeployConfig
): Promise<any> => {
// Very basic validation.
for (const [key, val] of Object.entries(cfg)) {
if (val === undefined) {
throw new Error(`must provide an input for config value: ${key}`)
}
} }
const variables = { const variables = {
OVM_DeployerWhitelist: { OVM_DeployerWhitelist: {
owner: cfg.whitelistOwner, owner: deployConfig.ovmWhitelistOwner,
}, },
OVM_GasPriceOracle: { OVM_GasPriceOracle: {
_owner: cfg.gasPriceOracleOwner, _owner: deployConfig.ovmGasPriceOracleOwner,
gasPrice: cfg.gasPriceOracleGasPrice, gasPrice: deployConfig.gasPriceOracleL2GasPrice,
l1BaseFee: cfg.gasPriceOracleL1BaseFee, l1BaseFee: deployConfig.gasPriceOracleL1BaseFee,
overhead: cfg.gasPriceOracleOverhead, overhead: deployConfig.gasPriceOracleOverhead,
scalar: cfg.gasPriceOracleScalar, scalar: deployConfig.gasPriceOracleScalar,
decimals: cfg.gasPriceOracleDecimals, decimals: deployConfig.gasPriceOracleDecimals,
}, },
L2StandardBridge: { L2StandardBridge: {
l1TokenBridge: cfg.l1StandardBridgeAddress, l1TokenBridge: (
await getContractFromArtifact(
hre,
names.managed.contracts.Proxy__OVM_L1StandardBridge
)
).address,
messenger: predeploys.L2CrossDomainMessenger, messenger: predeploys.L2CrossDomainMessenger,
}, },
OVM_SequencerFeeVault: { OVM_SequencerFeeVault: {
l1FeeWallet: cfg.l1FeeWalletAddress, l1FeeWallet: deployConfig.ovmFeeWalletAddress,
}, },
OVM_ETH: { OVM_ETH: {
l2Bridge: predeploys.L2StandardBridge, l2Bridge: predeploys.L2StandardBridge,
...@@ -89,7 +77,12 @@ export const makeL2GenesisFile = async ( ...@@ -89,7 +77,12 @@ export const makeL2GenesisFile = async (
// We default the xDomainMsgSender to this value to save gas. // We default the xDomainMsgSender to this value to save gas.
// See usage of this default in the L2CrossDomainMessenger contract. // See usage of this default in the L2CrossDomainMessenger contract.
xDomainMsgSender: '0x000000000000000000000000000000000000dEaD', xDomainMsgSender: '0x000000000000000000000000000000000000dEaD',
l1CrossDomainMessenger: cfg.l1CrossDomainMessengerAddress, l1CrossDomainMessenger: (
await getContractFromArtifact(
hre,
names.managed.contracts.Proxy__OVM_L1CrossDomainMessenger
)
).address,
// Set the messageNonce to a high value to avoid overwriting old sent messages. // Set the messageNonce to a high value to avoid overwriting old sent messages.
messageNonce: 100000, messageNonce: 100000,
}, },
...@@ -139,10 +132,10 @@ export const makeL2GenesisFile = async ( ...@@ -139,10 +132,10 @@ export const makeL2GenesisFile = async (
commit = '0000000000000000000000000000000000000000' commit = '0000000000000000000000000000000000000000'
} }
return { const genesis = {
commit, commit,
config: { config: {
chainId: cfg.l2ChainId, chainId: deployConfig.l2ChainId,
homesteadBlock: 0, homesteadBlock: 0,
eip150Block: 0, eip150Block: 0,
eip155Block: 0, eip155Block: 0,
...@@ -152,19 +145,27 @@ export const makeL2GenesisFile = async ( ...@@ -152,19 +145,27 @@ export const makeL2GenesisFile = async (
petersburgBlock: 0, petersburgBlock: 0,
istanbulBlock: 0, istanbulBlock: 0,
muirGlacierBlock: 0, muirGlacierBlock: 0,
berlinBlock: cfg.berlinBlock, berlinBlock: deployConfig.hfBerlinBlock,
clique: { clique: {
period: 0, period: 0,
epoch: 30000, epoch: 30000,
}, },
}, },
difficulty: '1', difficulty: '1',
gasLimit: cfg.l2BlockGasLimit.toString(10), gasLimit: deployConfig.l2BlockGasLimit.toString(10),
extradata: extradata:
'0x' + '0x' +
'00'.repeat(32) + '00'.repeat(32) +
remove0x(cfg.blockSignerAddress) + remove0x(deployConfig.ovmBlockSignerAddress) +
'00'.repeat(65), '00'.repeat(65),
alloc: dump, alloc: dump,
} }
}
// Make sure the output location exists
const outdir = path.resolve(__dirname, '../genesis')
const outfile = path.join(outdir, `${hre.network.name}.json`)
mkdirp.sync(outdir)
// Write the genesis file
fs.writeFileSync(outfile, JSON.stringify(genesis, null, 4))
})
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
], ],
"scripts": { "scripts": {
"start": "ts-node ./src/service.ts", "start": "ts-node ./src/service.ts",
"test:coverage": "echo 'No tests defined.'",
"build": "tsc -p ./tsconfig.build.json", "build": "tsc -p ./tsconfig.build.json",
"clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo", "clean": "rimraf dist/ ./tsconfig.build.tsbuildinfo",
"lint": "yarn lint:fix && yarn lint:check", "lint": "yarn lint:fix && yarn lint:check",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
], ],
"scripts": { "scripts": {
"start": "ts-node ./src/service", "start": "ts-node ./src/service",
"test:coverage": "echo 'No tests defined.'",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"clean": "rimraf ./dist ./tsconfig.build.tsbuildinfo", "clean": "rimraf ./dist ./tsconfig.build.tsbuildinfo",
"lint": "yarn run lint:fix && yarn run lint:check", "lint": "yarn run lint:fix && yarn run lint:check",
......
import { Provider } from '@ethersproject/abstract-provider' import { Provider, Block } from '@ethersproject/abstract-provider'
import { BaseServiceV2, Gauge, validators } from '@eth-optimism/common-ts' import {
BaseServiceV2,
Counter,
Gauge,
validators,
} from '@eth-optimism/common-ts'
import { sleep } from '@eth-optimism/core-utils' import { sleep } from '@eth-optimism/core-utils'
type HealthcheckOptions = { type HealthcheckOptions = {
...@@ -13,6 +18,8 @@ type HealthcheckMetrics = { ...@@ -13,6 +18,8 @@ type HealthcheckMetrics = {
isCurrentlyDiverged: Gauge isCurrentlyDiverged: Gauge
referenceHeight: Gauge referenceHeight: Gauge
targetHeight: Gauge targetHeight: Gauge
targetConnectionFailures: Counter
referenceConnectionFailures: Counter
} }
type HealthcheckState = {} type HealthcheckState = {}
...@@ -59,15 +66,48 @@ export class HealthcheckService extends BaseServiceV2< ...@@ -59,15 +66,48 @@ export class HealthcheckService extends BaseServiceV2<
type: Gauge, type: Gauge,
desc: 'Block height of the target client', desc: 'Block height of the target client',
}, },
targetConnectionFailures: {
type: Counter,
desc: 'Number of connection failures to the target client',
},
referenceConnectionFailures: {
type: Counter,
desc: 'Number of connection failures to the reference client',
},
}, },
}) })
} }
async main() { async main() {
const targetLatest = await this.options.targetRpcProvider.getBlock('latest') // Get the latest block from the target client and check for connection failures.
const referenceLatest = await this.options.referenceRpcProvider.getBlock( let targetLatest: Block
'latest' try {
) targetLatest = await this.options.targetRpcProvider.getBlock('latest')
} catch (err) {
if (err.message.includes('could not detect network')) {
this.logger.error('target client not connected')
this.metrics.targetConnectionFailures.inc()
return
} else {
throw err
}
}
// Get the latest block from the reference client and check for connection failures.
let referenceLatest: Block
try {
referenceLatest = await this.options.referenceRpcProvider.getBlock(
'latest'
)
} catch (err) {
if (err.message.includes('could not detect network')) {
this.logger.error('reference client not connected')
this.metrics.referenceConnectionFailures.inc()
return
} else {
throw err
}
}
// Update these metrics first so they'll refresh no matter what. // Update these metrics first so they'll refresh no matter what.
this.metrics.targetHeight.set(targetLatest.number) this.metrics.targetHeight.set(targetLatest.number)
......
...@@ -11106,9 +11106,9 @@ minimist-options@4.1.0, minimist-options@^4.0.2: ...@@ -11106,9 +11106,9 @@ minimist-options@4.1.0, minimist-options@^4.0.2:
kind-of "^6.0.3" kind-of "^6.0.3"
minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@~1.2.5: minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@~1.2.5:
version "1.2.5" version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
minipass-collect@^1.0.2: minipass-collect@^1.0.2:
version "1.0.2" version "1.0.2"
...@@ -11520,7 +11520,7 @@ node-fetch@2.6.1: ...@@ -11520,7 +11520,7 @@ node-fetch@2.6.1:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-fetch@^2.6.0, node-fetch@^2.6.1: node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7" version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment