From b6b13084dfa911b59007ae65c86ecf8f440a0830 Mon Sep 17 00:00:00 2001 From: Max Sanchez Date: Tue, 16 Apr 2024 14:41:29 -0400 Subject: [PATCH] Squashed 'heminetwork/' changes from b3993a073..88047e707 88047e707 Add tbcd, a small bitcoin daemon that participates on bitcoin p2p (#50) 1146a08b5 localnet reorg fix (#76) 87f18a191 build(deps): bump github.com/docker/docker (#64) 9073baeaf localnet (#37) 1588cbf04 Add common user-specific files to gitignore (#51) 210aabe7a Update popm.go, fix typo (#40) a5e689493 make: automate copyright headers (#31) 1c3bfc9bc Use `maps.Clone(m)` to copy returned map in `APICommands()` (#33) 1be4df2a3 Use 'errors.Is' to compare errors (#32) 3f6bc5f8e e2e: sync ElectrumX environment variables with infra (#36) c5b0fea01 electrumx: add connection reuse and pooling (#26) cfc1293e9 Update README.md (#29) 8896259f0 retry mine keystone on failure (#18) a10e3bb29 Use '%w' verb in fmt.Errorf to wrap errors (fixes #13) (#27) 6cd677611 deps: update google.golang.org/protobuf to v1.33.0 (#28) ed7eb8e97 ci: fix concurrency cancel-in-progress for pull requests (#16) ac3b7eacb docker: update golang image to v1.22.1 (#25) d6b0ac8af returning response errors if they exist from bfg -> popm (#24) d450b787a Network test start height + no panic (#22) b390805c5 allowing BTC Block and L2 Keystone generation rates to be configurable in local network (#19) bfd3b1dc0 make: add -local flag to goimports (#9) e0e8964fc Move internal error into protocol package (#10) 7875a897c l2 keystone mining fixes (#3) git-subtree-dir: heminetwork git-subtree-split: 88047e707e2db8522e2ad77c5f849e55bc94cd10 --- .github/workflows/go.yml | 3 +- .gitignore | 72 +- Makefile | 23 +- README.md | 32 +- api/api.go | 2 +- api/auth/secp256k1.go | 12 +- api/bfgapi/bfgapi.go | 3 +- api/bssapi/bssapi.go | 3 +- api/protocol/protocol.go | 96 +- api/tbcapi/tbcapi.go | 249 ++ bitcoin/bitcoin.go | 8 +- cmd/bfgd/bfgd.go | 7 +- cmd/bssd/bssd.go | 7 +- cmd/btctool/bdf/bdf.go | 231 ++ cmd/btctool/blockstream/blockstream.go | 97 + cmd/btctool/btctool.go | 694 ++++++ cmd/btctool/btctool/btctool.go | 37 + cmd/btctool/httpclient/httpclient.go | 50 + cmd/hemictl/hemictl.go | 540 ++++- cmd/keygen/keygen.go | 4 +- cmd/popmd/popmd.go | 13 +- cmd/tbcd/README.md | 56 + cmd/tbcd/tbcd.go | 178 ++ config/config.go | 4 +- database/bfgd/postgres/postgres.go | 31 +- database/bfgd/scripts/0001.sql | 4 + database/bfgd/scripts/0002.sql | 4 + database/bfgd/scripts/0003.sql | 4 + database/bfgd/scripts/0004.sql | 4 + database/bfgd/scripts/0005.sql | 4 + database/bfgd/scripts/0006.sql | 4 + database/database.go | 33 +- database/database_test.go | 31 + database/level/level.go | 211 ++ database/postgres/postgres.go | 10 +- database/tbcd/TESTS.md | 11 + database/tbcd/database.go | 371 +++ database/tbcd/database_ext_test.go | 5 + database/tbcd/level/level.go | 875 +++++++ database/tbcd/level/level_test.go | 419 ++++ docker/bfgd/Dockerfile | 6 +- docker/bssd/Dockerfile | 6 +- docker/popmd/Dockerfile | 6 +- e2e/.env | 7 + e2e/deploy-config.json | 58 + e2e/deployments/devnetL1/.chainId | 1 + e2e/deployments/devnetL1/AddressManager.json | 253 ++ e2e/deployments/devnetL1/BlockOracle.json | 207 ++ .../devnetL1/DisputeGameFactory.json | 637 +++++ .../devnetL1/DisputeGameFactoryProxy.json | 256 ++ .../devnetL1/L1CrossDomainMessenger.json | 822 +++++++ .../devnetL1/L1CrossDomainMessengerProxy.json | 116 + e2e/deployments/devnetL1/L1ERC721Bridge.json | 580 +++++ .../devnetL1/L1ERC721BridgeProxy.json | 256 ++ .../devnetL1/L1StandardBridge.json | 1186 +++++++++ .../devnetL1/L1StandardBridgeProxy.json | 182 ++ e2e/deployments/devnetL1/L2OutputOracle.json | 816 +++++++ .../devnetL1/L2OutputOracleProxy.json | 256 ++ e2e/deployments/devnetL1/Mips.json | 126 + .../OptimismMintableERC20Factory.json | 290 +++ .../OptimismMintableERC20FactoryProxy.json | 256 ++ e2e/deployments/devnetL1/OptimismPortal.json | 946 ++++++++ .../devnetL1/OptimismPortalProxy.json | 256 ++ e2e/deployments/devnetL1/PreimageOracle.json | 316 +++ .../devnetL1/ProtocolVersions.json | 407 ++++ .../devnetL1/ProtocolVersionsProxy.json | 256 ++ e2e/deployments/devnetL1/ProxyAdmin.json | 579 +++++ .../devnetL1/SafeProxyFactory.json | 226 ++ e2e/deployments/devnetL1/SafeSingleton.json | 1448 +++++++++++ .../devnetL1/SuperchainConfig.json | 280 +++ .../devnetL1/SuperchainConfigProxy.json | 256 ++ e2e/deployments/devnetL1/SystemConfig.json | 986 ++++++++ .../devnetL1/SystemConfigProxy.json | 256 ++ e2e/docker-compose.yml | 190 +- ...--78697c88847dfbbb40523e42c1f2e28a13a170be | 1 + ...--06f0f8ee8119b2a0b7a95ba267231be783d8d2ab | 1 + ...--7e7b60b907135c1a3d6844cfd3760b3143f5497a | 1 + e2e/e2e/passwords.txt | 1 + e2e/e2e_ext_test.go | 299 +-- e2e/entrypointl2.sh | 43 + e2e/genesisl2.sh | 75 + e2e/jwt.txt | 1 + e2e/mocktimism/Dockerfile | 4 + e2e/mocktimism/mocktimism.go | 27 +- e2e/network_test.go | 76 +- e2e/optimism-stack.Dockerfile | 51 + e2e/output/bytecode.txt | 1 + e2e/output/deployment.json | 7 + e2e/postgres.Dockerfile | 6 +- e2e/prestate-proof.json | 2 + go.mod | 253 +- go.sum | 914 +------ hemi/electrumx/conn.go | 183 ++ hemi/electrumx/conn_pool.go | 149 ++ hemi/electrumx/conn_pool_test.go | 114 + hemi/electrumx/conn_test.go | 305 +++ hemi/electrumx/electrumx.go | 152 +- hemi/pop/pop.go | 6 +- license_header.txt | 3 + service/bfg/bfg.go | 649 ++--- service/bfg/bfg_test.go | 6 +- service/bss/bss.go | 147 +- service/deucalion/deucalion.go | 4 +- service/popm/popm.go | 197 +- service/popm/popm_test.go | 635 ++++- service/popm/prometheus.go | 3 +- service/tbc/crawler.go | 444 ++++ service/tbc/crawler_test.go | 125 + service/tbc/peer.go | 202 ++ service/tbc/rpc.go | 559 +++++ service/tbc/tbc.go | 1777 ++++++++++++++ service/tbc/tbc_test.go | 2150 +++++++++++++++++ service/tbc/ulimit_darwin.go | 65 + service/tbc/ulimit_linux.go | 69 + service/tbc/ulimit_other.go | 13 + web/popminer/popminer.go | 7 +- web/www/index.html | 6 + web/www/index.js | 6 + web/www/popminer.js | 6 + 119 files changed, 25090 insertions(+), 1822 deletions(-) create mode 100644 api/tbcapi/tbcapi.go create mode 100644 cmd/btctool/bdf/bdf.go create mode 100644 cmd/btctool/blockstream/blockstream.go create mode 100644 cmd/btctool/btctool.go create mode 100644 cmd/btctool/btctool/btctool.go create mode 100644 cmd/btctool/httpclient/httpclient.go create mode 100644 cmd/tbcd/README.md create mode 100644 cmd/tbcd/tbcd.go create mode 100644 database/level/level.go create mode 100644 database/tbcd/TESTS.md create mode 100644 database/tbcd/database.go create mode 100644 database/tbcd/database_ext_test.go create mode 100644 database/tbcd/level/level.go create mode 100644 database/tbcd/level/level_test.go create mode 100644 e2e/.env create mode 100644 e2e/deploy-config.json create mode 100644 e2e/deployments/devnetL1/.chainId create mode 100644 e2e/deployments/devnetL1/AddressManager.json create mode 100644 e2e/deployments/devnetL1/BlockOracle.json create mode 100644 e2e/deployments/devnetL1/DisputeGameFactory.json create mode 100644 e2e/deployments/devnetL1/DisputeGameFactoryProxy.json create mode 100644 e2e/deployments/devnetL1/L1CrossDomainMessenger.json create mode 100644 e2e/deployments/devnetL1/L1CrossDomainMessengerProxy.json create mode 100644 e2e/deployments/devnetL1/L1ERC721Bridge.json create mode 100644 e2e/deployments/devnetL1/L1ERC721BridgeProxy.json create mode 100644 e2e/deployments/devnetL1/L1StandardBridge.json create mode 100644 e2e/deployments/devnetL1/L1StandardBridgeProxy.json create mode 100644 e2e/deployments/devnetL1/L2OutputOracle.json create mode 100644 e2e/deployments/devnetL1/L2OutputOracleProxy.json create mode 100644 e2e/deployments/devnetL1/Mips.json create mode 100644 e2e/deployments/devnetL1/OptimismMintableERC20Factory.json create mode 100644 e2e/deployments/devnetL1/OptimismMintableERC20FactoryProxy.json create mode 100644 e2e/deployments/devnetL1/OptimismPortal.json create mode 100644 e2e/deployments/devnetL1/OptimismPortalProxy.json create mode 100644 e2e/deployments/devnetL1/PreimageOracle.json create mode 100644 e2e/deployments/devnetL1/ProtocolVersions.json create mode 100644 e2e/deployments/devnetL1/ProtocolVersionsProxy.json create mode 100644 e2e/deployments/devnetL1/ProxyAdmin.json create mode 100644 e2e/deployments/devnetL1/SafeProxyFactory.json create mode 100644 e2e/deployments/devnetL1/SafeSingleton.json create mode 100644 e2e/deployments/devnetL1/SuperchainConfig.json create mode 100644 e2e/deployments/devnetL1/SuperchainConfigProxy.json create mode 100644 e2e/deployments/devnetL1/SystemConfig.json create mode 100644 e2e/deployments/devnetL1/SystemConfigProxy.json create mode 100644 e2e/e2e/keystore/UTC--2024-03-05T21-11-00.982268400Z--78697c88847dfbbb40523e42c1f2e28a13a170be create mode 100644 e2e/e2e/keystore/UTC--2024-03-05T21-11-09.690910600Z--06f0f8ee8119b2a0b7a95ba267231be783d8d2ab create mode 100644 e2e/e2e/keystore/UTC--2024-03-05T21-11-16.934955400Z--7e7b60b907135c1a3d6844cfd3760b3143f5497a create mode 100644 e2e/e2e/passwords.txt create mode 100644 e2e/entrypointl2.sh create mode 100644 e2e/genesisl2.sh create mode 100644 e2e/jwt.txt create mode 100644 e2e/optimism-stack.Dockerfile create mode 100644 e2e/output/bytecode.txt create mode 100644 e2e/output/deployment.json create mode 100755 e2e/prestate-proof.json create mode 100644 hemi/electrumx/conn.go create mode 100644 hemi/electrumx/conn_pool.go create mode 100644 hemi/electrumx/conn_pool_test.go create mode 100644 hemi/electrumx/conn_test.go create mode 100644 license_header.txt create mode 100644 service/tbc/crawler.go create mode 100644 service/tbc/crawler_test.go create mode 100644 service/tbc/peer.go create mode 100644 service/tbc/rpc.go create mode 100644 service/tbc/tbc.go create mode 100644 service/tbc/tbc_test.go create mode 100644 service/tbc/ulimit_darwin.go create mode 100644 service/tbc/ulimit_linux.go create mode 100644 service/tbc/ulimit_other.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 98f31d4c9320..0ae46ef9a76c 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,7 +14,7 @@ on: concurrency: group: "go-${{ github.workflow }}-${{ github.event.number || github.ref }}" - cancel-in-progress: "${{ github.event.action == 'push' || github.event.action == 'pull_request' }}" + cancel-in-progress: "${{ github.event_name == 'pull_request' }}" permissions: contents: read @@ -60,6 +60,7 @@ jobs: if: (success() || failure()) && steps.deps.outcome == 'success' env: PGTESTURI: "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable" + HEMI_DOCKER_TESTS: "1" run: | make git diff --exit-code diff --git a/.gitignore b/.gitignore index d17892227bf9..ef04addd361b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,73 @@ +### Hemi /bin/ /dist/ /pkg/ -.gocache -*.sw? +/.gocache/ + +## Tests +/service/tbc/.testleveldb/ + +### Common editors +## Vim +# Swap +[._]*.s[a-v][a-z] +!*.svg +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] +# Session +Session.vim +Sessionx.vim +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +## Emacs +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* +# Org-mode +.org-id-locations +*_archive +# flymake-mode +*_flymake.* +# eshell files +/eshell/history +/eshell/lastdir +# elpa packages +/elpa/ +# reftex files +*.rel +# AUCTeX auto folder +/auto/ +# cask packages +.cask/ +dist/ +# Flycheck +flycheck_*.el +# server auth directory +/server/ +# projectiles files +.projectile +# directory configuration +.dir-locals.el +# network security +/network-security.data + +## JetBrains +.idea/ +*.iml + +## Visual Studio Code +.vscode/ +.history/ diff --git a/Makefile b/Makefile index 0c30bff67bee..b0c26cb8cc71 100644 --- a/Makefile +++ b/Makefile @@ -20,24 +20,28 @@ project = heminetwork version = $(shell git describe --tags 2>/dev/null || echo "v0.0.0") cmds = \ - bfgd \ - bssd \ - extool \ - keygen \ - popmd \ - hemictl + bfgd \ + bssd \ + extool \ + hemictl \ + keygen \ + popmd \ + tbcd .PHONY: all clean clean-dist deps $(cmds) build install lint lint-deps tidy race test vulncheck \ vulncheck-deps dist archive sources checksums networktest all: lint tidy test build install -clean: clean-dist +clean: clean-dist clean-test rm -rf $(GOBIN) $(GOCACHE) $(GOPKG) clean-dist: rm -rf $(DIST) +clean-test: + rm -rf $(PROJECTPATH)/service/tbc/.testleveldb/ + deps: lint-deps vulncheck-deps go mod download go mod verify @@ -51,13 +55,16 @@ build: install: $(cmds) lint: - $(shell go env GOPATH)/bin/goimports -w -l . + $(shell go env GOPATH)/bin/goimports -local github.com/hemilabs/heminetwork -w -l . $(shell go env GOPATH)/bin/gofumpt -w -l . + $(shell go env GOPATH)/bin/addlicense -c "Hemi Labs, Inc." -f $(PROJECTPATH)/license_header.txt \ + -ignore "{.idea,.vscode}/**" -ignore ".github/release.yml" -ignore ".github/ISSUE_TEMPLATE/**" . go vet ./... lint-deps: GOBIN=$(shell go env GOPATH)/bin go install golang.org/x/tools/cmd/goimports@latest GOBIN=$(shell go env GOPATH)/bin go install mvdan.cc/gofumpt@latest + GOBIN=$(shell go env GOPATH)/bin go install github.com/google/addlicense@latest tidy: go mod tidy diff --git a/README.md b/README.md index bd64bd188d27..574bd1cb2f60 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ git clone https://github.com/hemilabs/heminetwork.git Then build: ```shell +cd heminetwork +make deps make ``` @@ -120,15 +122,37 @@ bssd has a few crucial requirements to run: Prerequisites: `docker` To run the full network locally, you can run the following. Note that this will create -L2Keytones and BTC Blocks at a high rate. You can modify these in `./e2e/mocktimism/mocktimism.go` -or `./e2e/docker-compose.yml`. +L2Keytones and BTC Blocks at a high rate. note: the `--build` flag is optional if you want to rebuild your code ``` -docker-compose -f ./e2e/docker-compose.yml up --build +docker compose -f ./e2e/docker-compose.yml up --build ``` +This will take a while upon first build, but following builds should be cached. +When rebuilding, popmd, bssd, and bfgd will rebuild (due to `COPY` command breaking + the cache). However if you want to break the cache for the op-stack, use the following args: + +For op-geth + optimism (op-node) +``` +docker compose -f ./e2e/docker-compose.yml build --build-arg OP_GETH_CACHE_BREAK="$(date)" +``` + +For optimism cache break only: +``` +docker compose -f ./e2e/docker-compose.yml build --build-arg OPTIMISM_CACHE_BREAK="$(date)" +``` + +**IMPORTANT:** make sure you run the following to tear down, this will remove +data and give you a fresh start + +``` +docker compose -f ./e2e/docker-compose.yml down -v --remove-orphans +``` + + + ### Running the full network tests This runs a test with an entirely local heminet, it uses bitcoind in regtest @@ -138,4 +162,4 @@ Prerequisites: `docker` ``` make networktest -``` \ No newline at end of file +``` diff --git a/api/api.go b/api/api.go index fcacf075ea52..beaa850621ae 100644 --- a/api/api.go +++ b/api/api.go @@ -11,7 +11,7 @@ import ( "strings" ) -// hexDecode decodes a string that may be prefixed with " and/or 0x. Thus +// hexDecode decodes a string that may be prefixed with " and/or 0x. Thus, // "0x00" and 0x00 or 00 are all valid hex encodings. If length is provided the // decoded size must exactly match. The length parameter will be ignored if it // is less than 0. diff --git a/api/auth/secp256k1.go b/api/auth/secp256k1.go index 8c0e5cf74913..2715857fa2f1 100644 --- a/api/auth/secp256k1.go +++ b/api/auth/secp256k1.go @@ -145,7 +145,7 @@ func (s *Secp256k1Auth) HandshakeClient(ctx context.Context, conn protocol.APICo for { _, _, payload, err := protocol.Read(ctx, conn, s) if err != nil { - return fmt.Errorf("read: %v", err) + return fmt.Errorf("read: %w", err) } log.Tracef(spew.Sdump(payload)) @@ -158,13 +158,13 @@ func (s *Secp256k1Auth) HandshakeClient(ctx context.Context, conn protocol.APICo hca, err := handleSecp256k1HelloChallenge(s.privKey, c) if err != nil { - return fmt.Errorf("handleSecp256k1HelloChallenge: %v", err) + return fmt.Errorf("handleSecp256k1HelloChallenge: %w", err) } requestID := "HelloChallengeAccepted:" + pubKey err = protocol.Write(ctx, conn, s, requestID, hca) if err != nil { - return fmt.Errorf("write HelloChallengeAccepted: %v", err) + return fmt.Errorf("write HelloChallengeAccepted: %w", err) } // Exit state machine @@ -186,7 +186,7 @@ func (s *Secp256k1Auth) HandshakeServer(ctx context.Context, conn protocol.APICo for { _, _, payload, err := protocol.Read(ctx, conn, s) if err != nil { - return fmt.Errorf("read: %v", err) + return fmt.Errorf("read: %w", err) } log.Tracef(spew.Sdump(payload)) @@ -206,7 +206,7 @@ func (s *Secp256k1Auth) HandshakeServer(ctx context.Context, conn protocol.APICo err = protocol.Write(ctx, conn, s, "HelloChallenge:"+c.PublicKey, hc) if err != nil { - return fmt.Errorf("write HelloChallenge: %v", err) + return fmt.Errorf("write HelloChallenge: %w", err) } case *Secp256k1HelloChallengeAccepted: @@ -220,7 +220,7 @@ func (s *Secp256k1Auth) HandshakeServer(ctx context.Context, conn protocol.APICo derived, err := handleSecp256k1HelloChallengeAccepted(am, c) if err != nil { - return fmt.Errorf("handleSecp256k1HelloChallengeAccepted: %v", err) + return fmt.Errorf("handleSecp256k1HelloChallengeAccepted: %w", err) } // Exit state machine diff --git a/api/bfgapi/bfgapi.go b/api/bfgapi/bfgapi.go index 5758aeb7eb81..eeb4c9cb031a 100644 --- a/api/bfgapi/bfgapi.go +++ b/api/bfgapi/bfgapi.go @@ -7,6 +7,7 @@ package bfgapi import ( "context" "fmt" + "maps" "reflect" "github.com/hemilabs/heminetwork/api" @@ -223,7 +224,7 @@ func (a *bfgAPI) Commands() map[protocol.Command]reflect.Type { } func APICommands() map[protocol.Command]reflect.Type { - return commands // XXX make copy + return maps.Clone(commands) } // Write is the low level primitive of a protocol Write. One should generally diff --git a/api/bssapi/bssapi.go b/api/bssapi/bssapi.go index b06ae1690593..12026de083e4 100644 --- a/api/bssapi/bssapi.go +++ b/api/bssapi/bssapi.go @@ -7,6 +7,7 @@ package bssapi import ( "context" "fmt" + "maps" "math/big" "reflect" @@ -134,7 +135,7 @@ func (a *apiCmd) Commands() map[protocol.Command]reflect.Type { } func APICommands() map[protocol.Command]reflect.Type { - return commands // XXX make copy + return maps.Clone(commands) } // Read reads a command from an APIConn. This is used server side. diff --git a/api/protocol/protocol.go b/api/protocol/protocol.go index 09a9ddd1cbe5..21331dd712eb 100644 --- a/api/protocol/protocol.go +++ b/api/protocol/protocol.go @@ -230,17 +230,18 @@ type Message struct { Payload json.RawMessage `json:"payload"` } -// Error is a protocol Error type that can be used for additional error -// context. It embeds an 8 byte number that can be used to trace calls on both the -// client and server side. +// Error is a protocol error type that is used to provide additional error +// information between a server and client. +// +// A unique "trace" string may be embedded, which can be used to trace errors +// between a server and client. type Error struct { Timestamp int64 `json:"timestamp"` - Trace string `json:"trace"` - Message string `json:"error"` + Trace string `json:"trace,omitempty"` + Message string `json:"message"` } -// Errorf is a client induced protocol error (e.g. "invalid height"). This is a -// pretty printable error on the client and server and is not fatal. +// Errorf returns a protocol Error type with an embedded trace. func Errorf(msg string, args ...interface{}) *Error { trace, _ := random(8) return &Error{ @@ -250,10 +251,87 @@ func Errorf(msg string, args ...interface{}) *Error { } } +// String pretty prints a protocol error. func (e Error) String() string { + if len(e.Trace) == 0 { + return e.Message + } return fmt.Sprintf("%v [%v:%v]", e.Message, e.Trace, e.Timestamp) } +func (e Error) Error() string { + return e.String() +} + +// RequestError wraps an error to create a protocol request error. +// +// Request errors are usually something caused by a client, e.g. validation or +// input errors, and therefore should not be logged server-side and do not +// contain an embedded trace. +func RequestError(err error) *Error { + return &Error{ + Timestamp: time.Now().Unix(), + Message: err.Error(), + } +} + +// RequestErrorf creates a new protocol request error. +// +// Request errors are usually something caused by a client, e.g. validation or +// input errors, and therefore should not be logged server-side and do not +// contain an embedded trace. +func RequestErrorf(msg string, args ...any) *Error { + return &Error{ + Timestamp: time.Now().Unix(), + Message: fmt.Sprintf(msg, args...), + } +} + +// InternalError represents an internal application error. +// +// Internal errors are errors that occurred within the application and are not +// caused by a client (e.g. validation or input errors). The actual error +// message should not be sent to clients, as it is internal to the application, +// and may be server-operator specific. +type InternalError struct { + protocol *Error + internal error +} + +// ProtocolError returns the protocol error representation. +// This error is intended to be sent to clients. +func (ie InternalError) ProtocolError() *Error { + return ie.protocol +} + +// Error satisfies the error interface. +func (ie InternalError) Error() string { + if ie.internal != nil { + return fmt.Sprintf("%v [%v:%v]", ie.internal.Error(), + ie.protocol.Timestamp, ie.protocol.Trace) + } + return ie.protocol.String() +} + +// Unwrap returns the error wrapped by this internal error. +func (ie InternalError) Unwrap() error { + return ie.internal +} + +// NewInternalError returns an InternalError wrapping the given error. +func NewInternalError(err error) *InternalError { + return NewInternalErrorf("internal error: %w", err) +} + +// NewInternalErrorf returns an InternalError constructed from the passed +// message and arguments. +func NewInternalErrorf(msg string, args ...interface{}) *InternalError { + return &InternalError{ + protocol: Errorf("internal error"), + internal: fmt.Errorf(msg, args...), + } +} + // Ping type PingRequest struct { Timestamp int64 `json:"timestamp"` // Local timestamp @@ -334,7 +412,7 @@ func (ac *Conn) Connect(ctx context.Context) error { log.Tracef("Connect: dialing %v", ac.serverURL) conn, _, err := websocket.Dial(connectCtx, ac.serverURL, nil) if err != nil { - return fmt.Errorf("failed to dial server: %v", err) + return fmt.Errorf("failed to dial server: %w", err) } conn.SetReadLimit(512 * 1024) // XXX - default is 32KB defer func() { @@ -416,7 +494,7 @@ func (ac *Conn) IsOnline() bool { return ac.wsc != nil } -// Close close a websocket connection with normal status. +// Close closes a websocket connection with normal status. func (ac *Conn) Close() error { return ac.CloseStatus(websocket.StatusNormalClosure, "") } diff --git a/api/tbcapi/tbcapi.go b/api/tbcapi/tbcapi.go new file mode 100644 index 000000000000..1b7e06e8250e --- /dev/null +++ b/api/tbcapi/tbcapi.go @@ -0,0 +1,249 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbcapi + +import ( + "context" + "fmt" + "maps" + "reflect" + + "github.com/hemilabs/heminetwork/api" + "github.com/hemilabs/heminetwork/api/protocol" +) + +const ( + APIVersion = 1 + + CmdPingRequest = "tbcapi-ping-request" + CmdPingResponse = "tbcapi-ping-response" + + CmdBlockHeadersByHeightRawRequest = "tbcapi-block-headers-by-height-raw-request" + CmdBlockHeadersByHeightRawResponse = "tbcapi-block-headers-by-height-raw-response" + + CmdBlockHeadersByHeightRequest = "tbcapi-block-headers-by-height-request" + CmdBlockHeadersByHeightResponse = "tbcapi-block-headers-by-height-response" + + CmdBlockHeadersBestRawRequest = "tbcapi-block-headers-best-raw-request" + CmdBlockHeadersBestRawResponse = "tbcapi-block-headers-best-raw-response" + + CmdBlockHeadersBestRequest = "tbcapi-block-headers-best-request" + CmdBlockHeadersBestResponse = "tbcapi-block-headers-best-response" + + CmdBalanceByAddressRequest = "tbcapi-balance-by-address-request" + CmdBalanceByAddressResponse = "tbcapi-balance-by-address-response" + + CmdUtxosByAddressRawRequest = "tbcapi-utxos-by-address-raw-request" + CmdUtxosByAddressRawResponse = "tbcapi-utxos-by-address-raw-response" + + CmdUtxosByAddressRequest = "tbcapi-utxos-by-address-request" + CmdUtxosByAddressResponse = "tbcapi-utxos-by-address-response" + + CmdTxByIdRawRequest = "tbcapi-tx-by-id-raw-request" + CmdTxByIdRawResponse = "tbcapi-tx-by-id-raw-response" + + CmdTxByIdRequest = "tbcapi-tx-by-id-request" + CmdTxByIdResponse = "tbcapi-tx-by-id-response" +) + +var ( + APIVersionRoute = fmt.Sprintf("v%d", APIVersion) + RouteWebsocket = fmt.Sprintf("/%s/ws", APIVersionRoute) + + DefaultListen = "localhost:8082" + DefaultURL = fmt.Sprintf("ws://%s/%s", DefaultListen, RouteWebsocket) +) + +type ( + PingRequest protocol.PingRequest + PingResponse protocol.PingResponse +) + +type BlockHeader struct { + Version int32 `json:"version"` + PrevHash string `json:"prev_hash"` + MerkleRoot string `json:"merkle_root"` + Timestamp int64 `json:"timestamp"` + Bits string `json:"bits"` + Nonce uint32 `json:"nonce"` +} + +type BlockHeadersByHeightRawRequest struct { + Height uint32 `json:"height"` +} + +type BlockHeadersByHeightRawResponse struct { + BlockHeaders []api.ByteSlice `json:"block_headers"` + Error *protocol.Error `json:"error,omitempty"` +} + +type BlockHeadersByHeightRequest struct { + Height uint32 `json:"height"` +} + +type BlockHeadersByHeightResponse struct { + BlockHeaders []*BlockHeader `json:"block_headers"` + Error *protocol.Error `json:"error,omitempty"` +} + +type BlockHeadersBestRawRequest struct{} + +type BlockHeadersBestRawResponse struct { + Height uint64 `json:"height"` + BlockHeaders []api.ByteSlice `json:"block_headers"` + Error *protocol.Error `json:"error,omitempty"` +} + +type BlockHeadersBestRequest struct{} + +type BlockHeadersBestResponse struct { + Height uint64 `json:"height"` + BlockHeaders []*BlockHeader `json:"block_headers"` + Error *protocol.Error `json:"error,omitempty"` +} + +type BalanceByAddressRequest struct { + Address string `json:"address"` +} + +type BalanceByAddressResponse struct { + Balance uint64 `json:"balance"` + Error *protocol.Error `json:"error,omitempty"` +} + +type UtxosByAddressRawRequest struct { + Address string `json:"address"` + Start uint `json:"start"` + Count uint `json:"count"` +} + +type UtxosByAddressRawResponse struct { + Utxos []api.ByteSlice `json:"utxos"` + Error *protocol.Error `json:"error,omitempty"` +} + +type UtxosByAddressRequest struct { + Address string `json:"address"` + Start uint `json:"start"` + Count uint `json:"count"` +} + +type Utxo struct { + TxId api.ByteSlice `json:"tx_id"` + Value uint64 `json:"value"` + OutIndex uint32 `json:"out_index"` +} + +type UtxosByAddressResponse struct { + Utxos []Utxo `json:"utxos"` + Error *protocol.Error `json:"error,omitempty"` +} + +type TxByIdRawRequest struct { + TxId api.ByteSlice `json:"tx_id"` +} + +type TxByIdRawResponse struct { + Tx api.ByteSlice `json:"tx"` + Error *protocol.Error `json:"error,omitempty"` +} + +type TxByIdRequest struct { + TxId api.ByteSlice `json:"tx_id"` +} + +type TxByIdResponse struct { + Tx Tx `json:"tx"` + Error *protocol.Error `json:"error,omitempty"` +} + +type OutPoint struct { + Hash api.ByteSlice `json:"hash"` + Index uint32 `json:"index"` +} + +type TxWitness []api.ByteSlice + +type TxIn struct { + PreviousOutPoint OutPoint `json:"outpoint"` + SignatureScript api.ByteSlice `json:"signature_script"` + Witness TxWitness `json:"tx_witness"` + Sequence uint32 `json:"sequence"` +} + +type TxOut struct { + Value int64 `json:"value"` + PkScript api.ByteSlice `json:"pk_script"` +} + +type Tx struct { + Version int32 `json:"version"` + LockTime uint32 `json:"lock_time"` + TxIn []*TxIn `json:"tx_in"` + TxOut []*TxOut `json:"tx_out"` +} + +var commands = map[protocol.Command]reflect.Type{ + CmdPingRequest: reflect.TypeOf(PingRequest{}), + CmdPingResponse: reflect.TypeOf(PingResponse{}), + CmdBlockHeadersByHeightRawRequest: reflect.TypeOf(BlockHeadersByHeightRawRequest{}), + CmdBlockHeadersByHeightRawResponse: reflect.TypeOf(BlockHeadersByHeightRawResponse{}), + CmdBlockHeadersByHeightRequest: reflect.TypeOf(BlockHeadersByHeightRequest{}), + CmdBlockHeadersByHeightResponse: reflect.TypeOf(BlockHeadersByHeightResponse{}), + CmdBlockHeadersBestRawRequest: reflect.TypeOf(BlockHeadersBestRawRequest{}), + CmdBlockHeadersBestRawResponse: reflect.TypeOf(BlockHeadersBestRawResponse{}), + CmdBlockHeadersBestRequest: reflect.TypeOf(BlockHeadersBestRequest{}), + CmdBlockHeadersBestResponse: reflect.TypeOf(BlockHeadersBestResponse{}), + CmdBalanceByAddressRequest: reflect.TypeOf(BalanceByAddressRequest{}), + CmdBalanceByAddressResponse: reflect.TypeOf(BalanceByAddressResponse{}), + CmdUtxosByAddressRawRequest: reflect.TypeOf(UtxosByAddressRawRequest{}), + CmdUtxosByAddressRawResponse: reflect.TypeOf(UtxosByAddressRawResponse{}), + CmdUtxosByAddressRequest: reflect.TypeOf(UtxosByAddressRequest{}), + CmdUtxosByAddressResponse: reflect.TypeOf(UtxosByAddressResponse{}), + CmdTxByIdRawRequest: reflect.TypeOf(TxByIdRawRequest{}), + CmdTxByIdRawResponse: reflect.TypeOf(TxByIdRawResponse{}), + CmdTxByIdRequest: reflect.TypeOf(TxByIdRequest{}), + CmdTxByIdResponse: reflect.TypeOf(TxByIdResponse{}), +} + +type tbcAPI struct{} + +func (a *tbcAPI) Commands() map[protocol.Command]reflect.Type { + return commands +} + +func APICommands() map[protocol.Command]reflect.Type { + return maps.Clone(commands) +} + +// Write is the low level primitive of a protocol Write. One should generally +// not use this function and use WriteConn and Call instead. +func Write(ctx context.Context, c protocol.APIConn, id string, payload any) error { + return protocol.Write(ctx, c, &tbcAPI{}, id, payload) +} + +// Read is the low level primitive of a protocol Read. One should generally +// not use this function and use ReadConn instead. +func Read(ctx context.Context, c protocol.APIConn) (protocol.Command, string, any, error) { + return protocol.Read(ctx, c, &tbcAPI{}) +} + +// Call is a blocking call. One should use ReadConn when using Call or else the +// completion will end up in the Read instead of being completed as expected. +func Call(ctx context.Context, c *protocol.Conn, payload any) (protocol.Command, string, any, error) { + return c.Call(ctx, &tbcAPI{}, payload) +} + +// WriteConn writes to Conn. It is equivalent to Write but exists for symmetry +// reasons. +func WriteConn(ctx context.Context, c *protocol.Conn, id string, payload any) error { + return c.Write(ctx, &tbcAPI{}, id, payload) +} + +// ReadConn reads from Conn and performs callbacks. One should use ReadConn over +// Read when mixing Write, WriteConn and Call. +func ReadConn(ctx context.Context, c *protocol.Conn) (protocol.Command, string, any, error) { + return c.Read(ctx, &tbcAPI{}) +} diff --git a/bitcoin/bitcoin.go b/bitcoin/bitcoin.go index 964994a3c3cc..ad8dd2bb3c25 100644 --- a/bitcoin/bitcoin.go +++ b/bitcoin/bitcoin.go @@ -117,14 +117,14 @@ func SignTx(btx *wire.MsgTx, payToScript []byte, privateKey *dcrsecp256k1.Privat txscript.SigHashAll, btx, 0, ) if err != nil { - return fmt.Errorf("failed to calculate signature hash: %v", err) + return fmt.Errorf("failed to calculate signature hash: %w", err) } pubKeyBytes := publicKey.SerializeCompressed() sig := dcrecdsa.Sign(privateKey, sigHash) sigBytes := append(sig.Serialize(), byte(txscript.SigHashAll)) sb := txscript.NewScriptBuilder().AddData(sigBytes).AddData(pubKeyBytes) if btx.TxIn[0].SignatureScript, err = sb.Script(); err != nil { - return fmt.Errorf("failed to build signature script: %v", err) + return fmt.Errorf("failed to build signature script: %w", err) } return nil } @@ -150,14 +150,14 @@ func PrivKeyFromHexString(s string) (*dcrsecp256k1.PrivateKey, error) { func KeysAndAddressFromHexString(s string, chainParams *chaincfg.Params) (*dcrsecp256k1.PrivateKey, *dcrsecp256k1.PublicKey, *btcutil.AddressPubKeyHash, error) { privKey, err := PrivKeyFromHexString(s) if err != nil { - return nil, nil, nil, fmt.Errorf("invalid BTC private key: %v", err) + return nil, nil, nil, fmt.Errorf("invalid BTC private key: %w", err) } pubKeyBytes := privKey.PubKey().SerializeCompressed() btcAddress, err := btcutil.NewAddressPubKey(pubKeyBytes, chainParams) if err != nil { return nil, nil, nil, - fmt.Errorf("failed to create BTC address from public key: %v", err) + fmt.Errorf("failed to create BTC address from public key: %w", err) } return privKey, privKey.PubKey(), btcAddress.AddressPubKeyHash(), nil diff --git a/cmd/bfgd/bfgd.go b/cmd/bfgd/bfgd.go index e8b8fbfc4d22..f480eb0a2011 100644 --- a/cmd/bfgd/bfgd.go +++ b/cmd/bfgd/bfgd.go @@ -6,6 +6,7 @@ package main import ( "context" + "errors" "fmt" "os" "os/signal" @@ -124,10 +125,10 @@ func _main() error { server, err := bfg.NewServer(cfg) if err != nil { - return fmt.Errorf("Failed to create BFG server: %v", err) + return fmt.Errorf("failed to create BFG server: %w", err) } - if err := server.Run(ctx); err != context.Canceled { - return fmt.Errorf("BFG server terminated: %v", err) + if err = server.Run(ctx); !errors.Is(err, context.Canceled) { + return fmt.Errorf("BFG server terminated: %w", err) } return nil diff --git a/cmd/bssd/bssd.go b/cmd/bssd/bssd.go index 4e04570d817f..af061e70ced2 100644 --- a/cmd/bssd/bssd.go +++ b/cmd/bssd/bssd.go @@ -6,6 +6,7 @@ package main import ( "context" + "errors" "fmt" "os" "os/signal" @@ -99,10 +100,10 @@ func _main() error { server, err := bss.NewServer(cfg) if err != nil { - return fmt.Errorf("Failed to create BSS server: %v", err) + return fmt.Errorf("failed to create BSS server: %w", err) } - if err := server.Run(ctx); err != context.Canceled { - return fmt.Errorf("BSS server terminated with error: %v", err) + if err := server.Run(ctx); !errors.Is(err, context.Canceled) { + return fmt.Errorf("BSS server terminated with error: %w", err) } return nil diff --git a/cmd/btctool/bdf/bdf.go b/cmd/btctool/bdf/bdf.go new file mode 100644 index 000000000000..4bc92af31e7d --- /dev/null +++ b/cmd/btctool/bdf/bdf.go @@ -0,0 +1,231 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package bdf + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "sync" + + "github.com/btcsuite/btcd/wire" + "github.com/juju/loggo" +) + +// XXX add tests + +var ( + log = loggo.GetLogger("bdf") + dfm sync.RWMutex +) + +const ( + DefaultNet = "testnet" + HeightFilename = "height" +) + +var DefaultDataDir = filepath.Join(DefaultNet, "bitcoin_headers") + +type LastHeight struct { + Height int `json:"height"` + Hash string `json:"hash"` +} + +type Header struct { + Height int `json:"height"` + Header string `json:"header"` +} + +func ReadHeight(filename string) (int, string, error) { + dfm.RLock() + defer dfm.RUnlock() + + f, err := os.Open(filename) + if err != nil { + return 0, "", err + } + d := json.NewDecoder(f) + var lh LastHeight + err = d.Decode(&lh) + if err != nil { + f.Close() + return 0, "", err + } + err = f.Close() + if err != nil { + return 0, "", err + } + return lh.Height, lh.Hash, nil +} + +func ReadHeader(filename string) (*wire.BlockHeader, int, error) { + dfm.RLock() + defer dfm.RUnlock() + + f, err := os.Open(filename) + if err != nil { + return nil, 0, err + } + d := json.NewDecoder(f) + var h Header + err = d.Decode(&h) + if err != nil { + f.Close() + return nil, 0, err + } + err = f.Close() + if err != nil { + return nil, 0, err + } + dh, err := hex.DecodeString(h.Header) + if err != nil { + return nil, 0, err + } + if len(dh) != 80 { + return nil, 0, err + } + var wbh wire.BlockHeader + err = wbh.Deserialize(bytes.NewReader(dh)) + if err != nil { + return nil, 0, err + } + return &wbh, h.Height, nil +} + +func Header2Bytes(wbh *wire.BlockHeader) ([]byte, error) { + var b bytes.Buffer + err := wbh.Serialize(&b) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +func Header2ExactBytes(wbh *wire.BlockHeader, header *[80]byte) error { + b, err := Header2Bytes(wbh) + if err != nil { + return err + } + if len(b) != 80 { + return fmt.Errorf("should not happen length %v", len(b)) + } + copy(header[:], b) + return nil +} + +func Header2Hex(wbh *wire.BlockHeader) (string, error) { + b, err := Header2Bytes(wbh) + if err != nil { + return "", err + } + return hex.EncodeToString(b), nil +} + +func Hex2Header(header string) (*wire.BlockHeader, error) { + blockHeader, err := hex.DecodeString(header) + if err != nil { + return nil, fmt.Errorf("DecodeString: %v", err) + } + var bh wire.BlockHeader + err = bh.Deserialize(bytes.NewReader(blockHeader)) + if err != nil { + return nil, fmt.Errorf("Deserialize: %v", err) + } + return &bh, nil +} + +// writeHeight reads the latest height and overwrites it if the provided height +// is higher. Poor mans for resolution :-) +func writeHeight(height int, hash, dir string) error { + log.Tracef("WriteHeight %v %v", height, hash) + defer log.Tracef("WriteHeight exit") + + var lh LastHeight + filename := filepath.Join(dir, HeightFilename) + f, err := os.Open(filename) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + // do nothing + defer f.Close() + } else { + return fmt.Errorf("Open: %v", err) + } + } else { + defer f.Close() + d := json.NewDecoder(f) + err = d.Decode(&lh) + if err != nil { + return fmt.Errorf("%v corrupt: %v", filename, err) + } + } + if lh.Height > height { + log.Tracef("not overwriting height: %v > %v", lh.Height, height) + return nil + } + fw, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) + if err != nil { + return fmt.Errorf("OpenFile: %v", err) + } + e := json.NewEncoder(fw) + lh.Height = height + lh.Hash = hash + err = e.Encode(lh) + if err != nil { + return fmt.Errorf("Encode: %v", err) + } + return fw.Close() +} + +// writeHeader writes a header. We pass the hash to verify that the header is correct. +func writeHeader(height int, hash, header, dir string) error { + filename := filepath.Join(dir, hash) + overwrite := false + if !overwrite { + _, err := os.Stat(filename) + if err == nil { + return fmt.Errorf("caught up at height: %v", height) + } + } + f, err := os.Create(filename) + if err != nil { + return fmt.Errorf("Create: %v", err) + } + e := json.NewEncoder(f) + err = e.Encode(Header{ + Height: height, + Header: header, + }) + if err != nil { + f.Close() + return fmt.Errorf("Encode: %v", err) + } + + return f.Close() +} + +func WriteHeader(height int, header, dir string) error { + bh, err := Hex2Header(header) + if err != nil { + return fmt.Errorf("Hex2Header: %v", err) + } + + dfm.Lock() + defer dfm.Unlock() + + err = writeHeader(height, bh.BlockHash().String(), header, dir) + if err != nil { + return fmt.Errorf("writeHeader: %v", err) + } + err = writeHeight(height, bh.BlockHash().String(), dir) + if err != nil { + return fmt.Errorf("writeHeight: %v", err) + } + return nil +} diff --git a/cmd/btctool/blockstream/blockstream.go b/cmd/btctool/blockstream/blockstream.go new file mode 100644 index 000000000000..839d1e8b4270 --- /dev/null +++ b/cmd/btctool/blockstream/blockstream.go @@ -0,0 +1,97 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package blockstream + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + + "github.com/hemilabs/heminetwork/cmd/btctool/httpclient" +) + +var ( + bsTestnetURL = "https://blockstream.info/testnet/api" // XXX wrap in structure + bsMainnetURL = "https://blockstream.info/api" // XXX wrap in structure + bsURL = bsTestnetURL // XXX wrap in structure +) + +type TBlock struct { + ID string `json:"id"` + Height uint `json:"height"` + Version uint `json:"version"` + Timestamp int64 `json:"timestamp"` + TxCount uint `json:"tx_count"` + Size uint `json:"size"` + Weight uint `json:"weight"` + MerkleRoot string `json:"merkle_root"` + PreviousBlockHash string `json:"previousblockhash"` + MedianTime int64 `json:"mediantime"` + Nonce uint `json:"nonce"` + Bits uint `json:"bits"` + Difficulty uint `json:"difficulty"` +} + +func Tip(ctx context.Context) (int, error) { + b, err := httpclient.Request(ctx, "GET", bsURL+"/blocks/tip/height", nil) + if err != nil { + return 0, fmt.Errorf("request: %v", err) + } + height, err := strconv.ParseInt(string(b), 10, 64) + if err != nil { + return 0, fmt.Errorf("ParseUint: %v", err) + } + + return int(height), nil +} + +func BlockHeader(ctx context.Context, hash string) (string, error) { + bh, err := httpclient.Request(ctx, "GET", bsURL+"/block/"+hash+"/header", nil) + if err != nil { + return "", fmt.Errorf("request: %v", err) + } + _, err = hex.DecodeString(string(bh)) + if err != nil { + return "", fmt.Errorf("DecodeString: %v", err) + } + return string(bh), nil +} + +func BlockHeightHash(ctx context.Context, height string) (string, error) { + bh, err := httpclient.Request(ctx, "GET", bsURL+"/block-height/"+height, nil) + if err != nil { + return "", fmt.Errorf("request: %v", err) + } + _, err = hex.DecodeString(string(bh)) + if err != nil { + return "", fmt.Errorf("DecodeString: %v", err) + } + return string(bh), nil +} + +func Block(ctx context.Context, hash string, raw bool) (string, error) { + suffix := "" + if raw { + suffix = "/raw" + } + b, err := httpclient.Request(ctx, "GET", bsURL+"/block/"+hash+suffix, nil) + if err != nil { + return "", fmt.Errorf("request: %v", err) + } + if raw { + return hex.EncodeToString(b), nil + } + return string(b), nil +} + +func BlockBytes(ctx context.Context, hash string) ([]byte, error) { + suffix := "/raw" + b, err := httpclient.Request(ctx, "GET", bsURL+"/block/"+hash+suffix, nil) + if err != nil { + return nil, fmt.Errorf("request: %v", err) + } + return b, nil +} diff --git a/cmd/btctool/btctool.go b/cmd/btctool/btctool.go new file mode 100644 index 000000000000..271553571af1 --- /dev/null +++ b/cmd/btctool/btctool.go @@ -0,0 +1,694 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package main // XXX wrap in structure + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "flag" + "fmt" + "math/rand" + "net" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" + "github.com/juju/loggo" + "github.com/mitchellh/go-homedir" + + "github.com/hemilabs/heminetwork/cmd/btctool/bdf" + "github.com/hemilabs/heminetwork/cmd/btctool/blockstream" + "github.com/hemilabs/heminetwork/cmd/btctool/btctool" +) + +var log = loggo.GetLogger("bdf") + +func parseBlockFromHex(blk string) (*btcutil.Block, error) { + eb, err := hex.DecodeString(strings.Trim(blk, "\n")) + if err != nil { + return nil, err + } + + // decode + b, err := btcutil.NewBlockFromBytes(eb) + if err != nil { + return nil, err + } + + return b, nil +} + +func parseBlock(ctx context.Context, filename string) (*btcutil.Block, error) { + heb, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + eb, err := hex.DecodeString(strings.Trim(string(heb), "\n")) + if err != nil { + return nil, err + } + fmt.Printf("len %v\n", len(eb)) + + // decode + b, err := btcutil.NewBlockFromBytes(eb) + if err != nil { + return nil, err + } + + return b, nil +} + +type peer struct { + mtx sync.RWMutex + address string + conn net.Conn + + protocolVersion uint32 + network wire.BitcoinNet + + remoteVersion *wire.MsgVersion + addrV2 bool +} + +func NewPeer(network wire.BitcoinNet, address string) (*peer, error) { + return &peer{ + protocolVersion: wire.ProtocolVersion, + network: network, + address: address, + }, nil +} + +func (p *peer) connect(ctx context.Context) error { + p.mtx.Lock() + if p.conn != nil { + p.mtx.Unlock() + return fmt.Errorf("already open") + } + p.mtx.Unlock() + // XXX this races + + d := net.Dialer{} + conn, err := d.DialContext(ctx, "tcp", p.address) + if err != nil { + return err + } + p.mtx.Lock() + p.conn = conn + p.mtx.Unlock() + + return nil +} + +func (p *peer) close() error { + p.mtx.Lock() + defer p.mtx.Unlock() + if p.conn != nil { + return p.conn.Close() + } + return fmt.Errorf("already closed") +} + +func (p *peer) write(msg wire.Message) error { + _, err := wire.WriteMessageWithEncodingN(p.conn, msg, p.protocolVersion, + p.network, wire.LatestEncoding) + return err +} + +func (p *peer) read() (wire.Message, error) { + _, msg, _, err := wire.ReadMessageWithEncodingN(p.conn, p.protocolVersion, + p.network, wire.LatestEncoding) + return msg, err +} + +func (p *peer) handshake(ctx context.Context) error { + // 1. send our version + // 2. receive version + // 3. send sendaddrv2 + // 4. send verack + // 5. receive sendaddrv2, verack or ignore + + us := &wire.NetAddress{Timestamp: time.Now()} + them := &wire.NetAddress{Timestamp: time.Now()} + msg := wire.NewMsgVersion(us, them, uint64(rand.Int63()), 0) + err := p.write(msg) + if err != nil { + return fmt.Errorf("could not write version message: %v", err) + } + + // 2. receive version + rmsg, err := p.read() + if err != nil { + return fmt.Errorf("could not read version message: %v", err) + } + v, ok := rmsg.(*wire.MsgVersion) + if !ok { + return fmt.Errorf("expected version message") + } + p.remoteVersion = v + + // 3. send sendaddrv2 + if v.ProtocolVersion >= 70016 { + err = p.write(wire.NewMsgSendAddrV2()) + if err != nil { + return fmt.Errorf("could not send sendaddrv2: %v", err) + } + } + + // 4. send verack + err = p.write(wire.NewMsgVerAck()) + if err != nil { + return fmt.Errorf("could not send verack: %v", err) + } + + for count := 0; count < 3; count++ { + msg, err := p.read() + if err == wire.ErrUnknownMessage { + continue + } else if err != nil { + return err + } + + switch msg.(type) { + case *wire.MsgVerAck: + return nil + case *wire.MsgSendAddrV2: + p.addrV2 = true + continue + default: + return fmt.Errorf("unexpected message type: %T", msg) + } + } + + return fmt.Errorf("handshake failed") +} + +func handlePing(p *peer, msg *wire.MsgPing) { + fmt.Printf("ping %v\n", msg.Nonce) + pong := wire.NewMsgPong(msg.Nonce) + err := p.write(pong) + if err != nil { + fmt.Printf("could not write pong message: %v", err) + return + } + fmt.Printf("wrote pong %v\n", pong.Nonce) +} + +func downloadBlock(p *peer, height int, hash chainhash.Hash) error { + fmt.Printf("get block at %v: %v\n", height, hash) + + getData := wire.NewMsgGetData() + getData.InvList = append(getData.InvList, + &wire.InvVect{ + Type: wire.InvTypeBlock, + Hash: hash, + }) + err := p.write(getData) + if err != nil { + return fmt.Errorf("could not write get block message: %v", err) + } + fmt.Printf("wrote get block %v\n", hash) + + return nil +} + +func handleInv(p *peer, msg *wire.MsgInv) { + fmt.Printf("inv: %v\n", len(msg.InvList)) + + for k := range msg.InvList { + switch msg.InvList[k].Type { + case wire.InvTypeBlock: + fmt.Printf("height %v hash %v\n", k+1, msg.InvList[k].Hash) + err := downloadBlock(p, k+1, msg.InvList[k].Hash) + if err != nil { + fmt.Printf("download block at %v: %v\n", k+1, err) + } + default: + fmt.Printf("skipping inv type: %v\n", msg.InvList[k].Type) + } + } +} + +func handleBlock(p *peer, msg *wire.MsgBlock) { + fmt.Printf("handle block: %v txs %v\n", msg.Header.BlockHash(), + len(msg.Transactions)) +} + +func btcConnect(ctx context.Context, btcNet string) error { + //ips, err := net.LookupIP("seed.bitcoin.sipa.be") + //if err != nil { + // return err + //} + + mainnetPort := "8333" + testnetPort := "18333" + var ( + port string + wireNet wire.BitcoinNet + chainParams *chaincfg.Params + ) + switch btcNet { + case "mainnet": + port = mainnetPort + wireNet = wire.MainNet + chainParams = &chaincfg.MainNetParams + case "testnet", "testnet3": + port = testnetPort + wireNet = wire.TestNet3 + chainParams = &chaincfg.TestNet3Params + default: + return fmt.Errorf("invalid network: %v", btcNet) + } + + p, err := NewPeer(wireNet, "140.238.169.133"+port) + if err != nil { + return fmt.Errorf("new peer: %v", err) + } + + err = p.connect(ctx) + if err != nil { + return fmt.Errorf("connect: %v", err) + } + + err = p.handshake(ctx) + if err != nil { + return fmt.Errorf("connect: %v", err) + } + + fmt.Printf("handshake complete with: %v\n", p.address) + + // send ibd start using get blocks + fmt.Printf("genesis hash: %v\n", chainParams.GenesisHash) + getBlocks := wire.NewMsgGetBlocks(chainParams.GenesisHash) + err = p.write(getBlocks) + if err != nil { + fmt.Printf("could not write getBlocks message: %v", err) + } + + verbose := false + for { + // see if we were interrupted + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + msg, err := p.read() + if err == wire.ErrUnknownMessage { + // skip unknown + continue + } else if err != nil { + return fmt.Errorf("read: %w", err) + } + + if verbose { + spew.Dump(msg) + } + + switch m := msg.(type) { + case *wire.MsgPing: + go handlePing(p, m) + + case *wire.MsgInv: + go handleInv(p, m) + + case *wire.MsgBlock: + go handleBlock(p, m) + + default: + fmt.Printf("unhandled message type: %T\n", msg) + } + } + + //fmt.Printf("waiting for exit\n") + //<-ctx.Done() + //return nil + + //peers := make(map[string]*peer, len(ips)) + //ips = []net.IP{ + // net.ParseIP("140.238.169.133"), + // // net.ParseIP("84.250.91.34"), + // // net.ParseIP("3.14.15.90"), + // // net.ParseIP("104.182.210.230"), + //} + //for _, ip := range ips { + // address := ip.To4() + // if address == nil { + // continue + // } + // // XXX this does not test for link local and other exclusions + + // // Should be an IPv4 address here + // ma := fmt.Sprintf("%v:%v", address, port) + // p := &peer{address: ma} + // peers[ma] = p + + // // connect + // go func(pp *peer) { + // err := pp.connect(ctx) + // if err != nil { + // fmt.Printf("err: %v\n", err) + // } else { + // fmt.Printf("connected: %v\n", pp.address) + + // pver := wire.ProtocolVersion + + // // write ver + // me := &wire.NetAddress{ + // Timestamp: time.Now(), + // Services: wire.SFNodeNetwork, + // // IP: net.ParseIP("193.218.159.178"), + // // Port: 18333, + + // } + // // spew.Dump(pp.conn.LocalAddr()) + // // theirIP := pp.conn.RemoteAddr().String() + // you := &wire.NetAddress{ + // Timestamp: time.Now(), + // // IP: ips[0], + // // Port: 18333, + // // Services: wire.SFNodeNetwork, + // } + // // spew.Dump(me) + // // spew.Dump(theirIP) + // wmsg := wire.NewMsgVersion(me, you, uint64(rand.Int63()), 0) + // wmsg.Services = wire.SFNodeNetwork + // wmsg.DisableRelayTx = true + // spew.Dump(wmsg) + // n, err := wire.WriteMessageWithEncodingN(pp.conn, wmsg, pver, wireNet, wire.LatestEncoding) + // if err != nil { + // fmt.Printf("write error: %v\n", err) + // return + // } + // fmt.Printf("write n NewMsgVersion: %v\n", n) + + // n, rmsg, rawPayload, err := wire.ReadMessageWithEncodingN(pp.conn, pver, wireNet, wire.LatestEncoding) + // fmt.Printf("read n %T: %v\n", rmsg, n) + // if err != nil { + // fmt.Printf("read error: %v\n", err) + // return + + // } + // _ = rawPayload + // fmt.Printf("%v\n", spew.Sdump(rmsg)) + // // fmt.Printf("%v\n", spew.Sdump(rawPayload)) + // v := rmsg.(*wire.MsgVersion) + // if v.ProtocolVersion >= 70016 { + // fmt.Printf("sendaddrv2\n") + // sendAddrMsg := wire.NewMsgSendAddrV2() + // n, err := wire.WriteMessageWithEncodingN(pp.conn, sendAddrMsg, pver, wireNet, wire.LatestEncoding) + // if err != nil { + // fmt.Printf("write error: %v\n", err) + // return + // } + // fmt.Printf("write n MsgSendAddrV2: %v\n", n) + // } + + // // send verack + // verack := wire.NewMsgVerAck() + // n, err = wire.WriteMessageWithEncodingN(pp.conn, verack, pver, wireNet, wire.LatestEncoding) + // if err != nil { + // fmt.Printf("write error: %v\n", err) + // return + // } + // fmt.Printf("write n MsgVerAck: %v\n", n) + + // for { + // // read what comes back + // n, rmsg, rawPayload, err = wire.ReadMessageWithEncodingN(pp.conn, pver, wireNet, wire.LatestEncoding) + // fmt.Printf("read n %T: %v\n", rmsg, n) + // if err != nil { + // fmt.Printf("read error continue: %v\n", err) + // // XXX exit if eof + // continue + + // } + // _ = rawPayload + // fmt.Printf("%v\n", spew.Sdump(rmsg)) + // } + // } + // }(p) + //} + + //<-ctx.Done() + + // return nil +} + +func StoreBlockHeaders(ctx context.Context, endHeight, blockCount int, dir string) error { + for h := 0; h < blockCount; h++ { + height := endHeight - blockCount + h + 1 + hash, err := btctool.GetAndStoreBlockHeader(ctx, height, dir) + if err != nil { + return err + } + fmt.Printf("%v: %v\n", height, hash) + } + return nil +} + +func parseArgs(args []string) (string, map[string]string, error) { + if len(args) < 1 { + flag.Usage() + return "", nil, fmt.Errorf("action required") + } + + action := args[0] + parsed := make(map[string]string, 10) + + for _, v := range args[1:] { + s := strings.Split(v, "=") + if len(s) != 2 { + return "", nil, fmt.Errorf("invalid argument: %v", v) + } + if len(s[0]) == 0 || len(s[1]) == 0 { + return "", nil, fmt.Errorf("expected a=b, got %v", v) + } + parsed[s[0]] = s[1] + } + + return action, parsed, nil +} + +func addressToScript(addr string) (btcutil.Address, error) { + return btcutil.DecodeAddress(addr, &chaincfg.TestNet3Params) +} + +func init() { +} + +func _main() error { + flag.Usage = func() { + f := flag.CommandLine.Output() + fmt.Fprintf(f, "Usage of %v \n", os.Args[0]) + fmt.Fprintf(f, "Flags:\n") + flag.PrintDefaults() + fmt.Fprintf(f, "Actions:\n") + fmt.Fprintf(f, " block [json=bool] [wire=bool] - retrieve block for hash\n") + fmt.Fprintf(f, " blockheader - retrieve blockheader for hash\n") + fmt.Fprintf(f, " blockheighthash - block hash at height\n") + fmt.Fprintf(f, " storeblockheaders [start=int] [count=int] - store block headers\n") + fmt.Fprintf(f, " tip - retrieve tip height\n") + } + + //var ( + // endHeight, blockCount int + // downloadDir string + //) + //flag.IntVar(&endHeight, "startblock", -1, "Height to start downloading, negative means start at current max height") + //flag.IntVar(&blockCount, "count", -1024, "number of blocks to download, negative goes backwards from height") + //flag.StringVar(&downloadDir, "downloaddir", "", "Directory to download block header and data to. Leave empty to dump to stdout.") + flag.Parse() + + err := loggo.ConfigureLoggers("info") // XXX make flag + if err != nil { + return fmt.Errorf("ConfigureLoggers: %v", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + _ = cancel + + action, args, err := parseArgs(flag.Args()) + if err != nil { + return err + } + + switch action { + case "standardscript": + address := args["address"] + if address == "" { + return fmt.Errorf("address: must be set") + } + var ( + a btcutil.Address + h []byte + sh [32]byte + ) + a, err = addressToScript(address) + h, err = txscript.PayToAddrScript(a) + sh = sha256.Sum256(h) + spew.Dump(a) + spew.Dump(h) + spew.Dump(sh) + + case "block": + raw := true + + wireSpew := false + wireSet := args["wire"] + if wireSet == "1" || strings.ToLower(wireSet) == "true" { + wireSpew = true + } + + jsonSet := args["json"] + if jsonSet == "1" || strings.ToLower(jsonSet) == "true" { + raw = false + if wireSpew { + return fmt.Errorf("wire and json may not be both set") + } + } + hash := args["hash"] + if hash == "" { + return fmt.Errorf("hash: must be set") + } + var b string + b, err = blockstream.Block(ctx, hash, raw) + if err == nil { + if wireSpew { + //eb, err := hex.DecodeString(strings.Trim(b, "\n")) + //if err != nil { + // return err + //} + //fmt.Printf("%v", spew.Sdump(eb)) + + blk, err := parseBlockFromHex(b) + if err != nil { + return err + } + fmt.Printf("%v", spew.Sdump(blk.MsgBlock())) + } else { + fmt.Printf("%v\n", b) + } + } + case "blockheader": + hash := args["hash"] + if hash == "" { + return fmt.Errorf("hash: must be set") + } + var bh string + bh, err = blockstream.BlockHeader(ctx, hash) + if err == nil { + fmt.Printf("%v\n", bh) + } + case "blockheighthash": + height := args["height"] + if height == "" { + return fmt.Errorf("height: must be set") + } + var bh string + bh, err = blockstream.BlockHeightHash(ctx, height) + if err == nil { + fmt.Printf("%v\n", bh) + } + case "tip": + var height int + height, err = blockstream.Tip(ctx) + if err == nil { + fmt.Printf("%v\n", height) + } + + case "p2p": + err = btcConnect(ctx, "testnet3") + + case "parseblock": + filename := args["filename"] + if filename == "" { + return fmt.Errorf("filename: must be set") + } + var block *btcutil.Block + block, err = parseBlock(ctx, filename) + if err == nil { + spew.Dump(block) + } + + case "storeblockheaders": + // XXX remove + kill bfd + downloadDir := filepath.Join("~/.mocksicle", bdf.DefaultDataDir) + downloadDir, err = homedir.Expand(downloadDir) + if err != nil { + return fmt.Errorf("invalid directory: %v", err) + } + + err = os.MkdirAll(downloadDir, 0o700) + if err != nil { + return fmt.Errorf("MkdirAll: %v", err) + } + + blockCount := int(1024) + count := args["count"] + if count != "" { + bc, err := strconv.ParseInt(count, 10, 64) + if err != nil { + return fmt.Errorf("count: %v", err) + } + if bc < 0 { + return fmt.Errorf("count must not be negative: %v", bc) + } + blockCount = int(bc) + } + + // Where do we end + var endHeight int + end := args["end"] + if end == "" { + endHeight, err = blockstream.Tip(ctx) + if err != nil { + return fmt.Errorf("tip: %v", err) + } + } else { + e, err := strconv.ParseInt(end, 10, 64) + if err != nil { + return fmt.Errorf("end: %v", err) + } + if e < 0 { + bh, err := blockstream.Tip(ctx) + if err != nil { + return fmt.Errorf("tip: %v", err) + } + e = int64(bh) + e + if e < 0 { + return fmt.Errorf("end height must not be "+ + "negative: %v", e) + } + fmt.Printf("tip at %v, downloading to %v\n", bh, e) + } + endHeight = int(e) + } + err = StoreBlockHeaders(ctx, endHeight, blockCount, downloadDir) + default: + return fmt.Errorf("invalid action: %v", os.Args[1]) + } + + return err +} + +func main() { + err := _main() + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + return +} diff --git a/cmd/btctool/btctool/btctool.go b/cmd/btctool/btctool/btctool.go new file mode 100644 index 000000000000..24caf5ce0467 --- /dev/null +++ b/cmd/btctool/btctool/btctool.go @@ -0,0 +1,37 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package btctool + +import ( + "context" + "fmt" + + "github.com/juju/loggo" + + "github.com/hemilabs/heminetwork/cmd/btctool/bdf" + "github.com/hemilabs/heminetwork/cmd/btctool/blockstream" +) + +var log = loggo.GetLogger("btctool") + +func GetAndStoreBlockHeader(ctx context.Context, height int, dir string) (string, error) { + hash, err := blockstream.BlockHeightHash(ctx, fmt.Sprintf("%v", height)) + if err != nil { + return "", fmt.Errorf("BlockHeightHash %v: %v", height, err) + } + + header, err := blockstream.BlockHeader(ctx, hash) + if err != nil { + return "", fmt.Errorf("BlockHeader %v: %v", hash, err) + } + + // Write header + err = bdf.WriteHeader(height, header, dir) + if err != nil { + return "", fmt.Errorf("WriteHeight: %v", err) + } + + return hash, nil +} diff --git a/cmd/btctool/httpclient/httpclient.go b/cmd/btctool/httpclient/httpclient.go new file mode 100644 index 000000000000..5e4b6d0b80ca --- /dev/null +++ b/cmd/btctool/httpclient/httpclient.go @@ -0,0 +1,50 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package httpclient + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "time" +) + +func Request(ctx context.Context, method, url string, body any) ([]byte, error) { + var r io.Reader + if body != nil { + b, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("marshal body: %v", err) + } + r = bytes.NewReader(b) + } + c := &http.Client{} + for retry := 1; ; retry++ { + req, err := http.NewRequestWithContext(ctx, method, url, r) + if err != nil { + return nil, fmt.Errorf("NewRequestWithContext: %v", err) + } + resp, err := c.Do(req) + if err != nil { + return nil, fmt.Errorf("Do: %v", err) + } + defer resp.Body.Close() + + switch resp.StatusCode { + case http.StatusOK: + case http.StatusTooManyRequests: + time.Sleep(time.Duration(retry) * time.Second) + continue + default: + return nil, fmt.Errorf("%v %v %v %v", method, url, + resp.StatusCode, http.StatusText(resp.StatusCode)) + } + + return io.ReadAll(resp.Body) + } +} diff --git a/cmd/hemictl/hemictl.go b/cmd/hemictl/hemictl.go index dc6036e64580..8006c6719556 100644 --- a/cmd/hemictl/hemictl.go +++ b/cmd/hemictl/hemictl.go @@ -7,7 +7,11 @@ package main import ( "bytes" "context" + "crypto/sha256" + "encoding/binary" + "encoding/hex" "encoding/json" + "errors" "flag" "fmt" "io" @@ -17,19 +21,31 @@ import ( "reflect" "regexp" "sort" + "strconv" "strings" "sync" "time" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/davecgh/go-spew/spew" "github.com/juju/loggo" "github.com/mitchellh/go-homedir" + "github.com/syndtr/goleveldb/leveldb/util" "github.com/hemilabs/heminetwork/api/bfgapi" "github.com/hemilabs/heminetwork/api/bssapi" "github.com/hemilabs/heminetwork/api/protocol" + "github.com/hemilabs/heminetwork/api/tbcapi" "github.com/hemilabs/heminetwork/config" + "github.com/hemilabs/heminetwork/database" "github.com/hemilabs/heminetwork/database/bfgd/postgres" + ldb "github.com/hemilabs/heminetwork/database/level" + "github.com/hemilabs/heminetwork/database/tbcd" + "github.com/hemilabs/heminetwork/database/tbcd/level" + "github.com/hemilabs/heminetwork/service/tbc" "github.com/hemilabs/heminetwork/version" ) @@ -84,6 +100,16 @@ func handleBFGWebsocketReadUnauth(ctx context.Context, conn *protocol.Conn) { } } +// handleTBCWebsocketRead discards all reads but has to exist in order to +// be able to use tbcapi.Call. +func handleTBCWebsocketRead(ctx context.Context, conn *protocol.Conn) { + for { + if _, _, _, err := tbcapi.ReadConn(ctx, conn); err != nil { + return + } + } +} + func bfgdb() error { ctx, cancel := context.WithTimeout(context.Background(), callTimeout) defer cancel() @@ -93,24 +119,24 @@ func bfgdb() error { // construct pgURI based on reasonable defaults. home, err := homedir.Dir() if err != nil { - return fmt.Errorf("Dir: %v", err) + return fmt.Errorf("dir: %w", err) } user, err := user.Current() if err != nil { - return fmt.Errorf("Current: %v", err) + return fmt.Errorf("current: %w", err) } filename := filepath.Join(home, ".pgsql-bfgdb-"+user.Username) password, err := os.ReadFile(filename) if err != nil { - return fmt.Errorf("ReadFile: %v", err) + return fmt.Errorf("read file: %w", err) } pgURI = fmt.Sprintf("database=bfgdb password=%s", password) } db, err := postgres.New(ctx, pgURI) if err != nil { - return fmt.Errorf("New: %v", err) + return fmt.Errorf("new: %w", err) } defer db.Close() @@ -130,13 +156,499 @@ func bfgdb() error { o, err := json.Marshal(out) if err != nil { - return fmt.Errorf("marshal: %v", err) + return fmt.Errorf("marshal: %w", err) } fmt.Printf("%s\n", o) return nil } +func parseArgs(args []string) (string, map[string]string, error) { + if len(args) < 1 { + flag.Usage() + return "", nil, fmt.Errorf("action required") + } + + action := args[0] + parsed := make(map[string]string, 10) + + for _, v := range args[1:] { + s := strings.Split(v, "=") + if len(s) != 2 { + return "", nil, fmt.Errorf("invalid argument: %v", v) + } + if len(s[0]) == 0 || len(s[1]) == 0 { + return "", nil, fmt.Errorf("expected a=b, got %v", v) + } + parsed[s[0]] = s[1] + } + + return action, parsed, nil +} + +func tbcdb() error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + action, args, err := parseArgs(flag.Args()[1:]) + if err != nil { + return err + } + + // special commands + //switch action { + //case "crossreference": + // return crossReference(ctx) + //} + + // create fake service to call crawler + cfg := tbc.NewDefaultConfig() + cfg.LevelDBHome = "~/.tbcd" + cfg.Network = "testnet3" + s, err := tbc.NewServer(cfg) + if err != nil { + return fmt.Errorf("new server: %w", err) + } + // Open db. + err = s.DBOpen(ctx) + if err != nil { + return fmt.Errorf("db open: %w", err) + } + defer func() { + err := s.DBClose() + if err != nil { + fmt.Fprintf(os.Stderr, "db close: %v\n", err) + os.Exit(1) + } + }() + + // commands + switch action { + case "blockheaderbyhash": + hash := args["hash"] + if hash == "" { + return fmt.Errorf("hash: must be set") + } + ch, err := chainhash.NewHashFromStr(hash) + if err != nil { + return fmt.Errorf("chainhash: %w", err) + } + bh, err := s.DB().BlockHeaderByHash(ctx, ch[:]) + if err != nil { + return fmt.Errorf("block header by hash: %w", err) + } + fmt.Printf("hash : %v\n", bh) + fmt.Printf("height: %v\n", bh.Height) + + case "blockheadersbest": + bhs, err := s.DB().BlockHeadersBest(ctx) + if err != nil { + return fmt.Errorf("block headers best: %w", err) + } + for k := range bhs { + fmt.Printf("hash (%v): %v\n", k, bhs[k]) + fmt.Printf("height (%v): %v\n", k, bhs[k].Height) + } + + case "blockheadersbyheight": + height := args["height"] + if height == "" { + return fmt.Errorf("height: must be set") + } + h, err := strconv.ParseUint(height, 10, 64) + if err != nil { + return fmt.Errorf("parse uint: %w", err) + } + bh, err := s.DB().BlockHeadersByHeight(ctx, h) + if err != nil { + return fmt.Errorf("block header by height: %w", err) + } + spew.Dump(bh) + + // case "blockheadersinsert": + + case "blocksmissing": + count := args["count"] + c, err := strconv.ParseUint(count, 10, 64) + if len(count) > 0 && err != nil { + return fmt.Errorf("parse uint: %w", err) + } + if c == 0 { + c = 1 + } + bh, err := s.DB().BlocksMissing(ctx, int(c)) + if err != nil { + return fmt.Errorf("block header by height: %w", err) + } + spew.Dump(bh) + + // case "blockinsert": + + case "blockbyhash": + hash := args["hash"] + if hash == "" { + return fmt.Errorf("hash: must be set") + } + ch, err := chainhash.NewHashFromStr(hash) + if err != nil { + return fmt.Errorf("chainhash: %w", err) + } + b, err := s.DB().BlockByHash(ctx, ch[:]) + if err != nil { + return fmt.Errorf("block by hash: %w", err) + } + spew.Dump(b) + + case "deletemetadata": + key := args["key"] + if key == "" { + return fmt.Errorf("key: must be set") + } + + s.DBClose() + + levelDBHome := "~/.tbcd" // XXX + network := "testnet3" + db, err := level.New(ctx, filepath.Join(levelDBHome, network)) + if err != nil { + return err + } + defer db.Close() + pool := db.DB() + mdDB := pool[ldb.MetadataDB] + err = mdDB.Delete([]byte(key), nil) + if err != nil { + return err + } + + case "dumpmetadata": + s.DBClose() + + levelDBHome := "~/.tbcd" // XXX + network := "testnet3" + db, err := level.New(ctx, filepath.Join(levelDBHome, network)) + if err != nil { + return err + } + defer db.Close() + pool := db.DB() + mdDB := pool[ldb.MetadataDB] + it := mdDB.NewIterator(nil, nil) + defer it.Release() + for it.Next() { + fmt.Printf("metadata key %vvalue %v", spew.Sdump(it.Key()), spew.Sdump(it.Value())) + } + + case "dumpoutputs": + s.DBClose() + + levelDBHome := "~/.tbcd" // XXX + network := "testnet3" + db, err := level.New(ctx, filepath.Join(levelDBHome, network)) + if err != nil { + return err + } + defer db.Close() + prefix := args["prefix"] + if len(prefix) > 1 { + return fmt.Errorf("prefix must be one byte") + } else if len(prefix) == 1 && !(prefix[0] == 'h' || prefix[0] == 'u') { + return fmt.Errorf("prefix must be h or u") + } + pool := db.DB() + outsDB := pool[ldb.OutputsDB] + it := outsDB.NewIterator(&util.Range{Start: []byte(prefix)}, nil) + defer it.Release() + for it.Next() { + fmt.Printf("outputs key %vvalue %v", spew.Sdump(it.Key()), spew.Sdump(it.Value())) + } + + case "feesbyheight": + height := args["height"] + if height == "" { + return fmt.Errorf("height: must be set") + } + h, err := strconv.ParseInt(height, 10, 64) + if err != nil { + return fmt.Errorf("parse uint: %w", err) + } + count := args["count"] + c, err := strconv.ParseInt(count, 10, 64) + if len(count) > 0 && err != nil { + return fmt.Errorf("parse uint: %w", err) + } + if c == 0 { + c = 1 + } + bh, err := s.FeesAtHeight(ctx, h, c) + if err != nil { + return fmt.Errorf("fees by height: %w", err) + } + spew.Dump(bh) + + case "help", "h": + fmt.Printf("tbcd db manipulator commands:\n") + fmt.Printf("\tbalancebyscripthash [hash]\n") + fmt.Printf("\tblockbyhash [hash]\n") + fmt.Printf("\tblockheaderbyhash [hash]\n") + fmt.Printf("\tblockheadersbest\n") + fmt.Printf("\tblockheadersbyheight [height]\n") + fmt.Printf("\tblocksbytxid [hash]\n") + fmt.Printf("\tblocksmissing [count]\n") + fmt.Printf("\tdeletemetadata\n") + fmt.Printf("\tdumpmetadata\n") + fmt.Printf("\tdumpoutputs \n") + fmt.Printf("\thelp\n") + fmt.Printf("\tscripthashbyoutpoint [txid] [index]\n") + fmt.Printf("\tspendoutputsbytxid [txid] [index]\n") + fmt.Printf("\ttxindex \n") + fmt.Printf("\tutxoindex \n") + fmt.Printf("\tutxosbyscripthash [hash]\n") + + case "utxoindex": + var h, c, mc uint64 + height := args["height"] + if height == "" { + // Get height from db + he, err := s.DB().MetadataGet(ctx, tbc.UtxoIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + return fmt.Errorf("metadata %v: %w", + string(tbc.UtxoIndexHeightKey), err) + } + he = make([]byte, 8) + } + h = binary.BigEndian.Uint64(he) + } else if h, err = strconv.ParseUint(height, 10, 64); err != nil { + return fmt.Errorf("height: %w", err) + } + count := args["count"] + if count == "" { + c = 0 + } else if c, err = strconv.ParseUint(count, 10, 64); err != nil { + return fmt.Errorf("count: %w", err) + } + maxCache := args["maxcache"] + if maxCache != "" { + if mc, err = strconv.ParseUint(maxCache, 10, 64); err != nil { + return fmt.Errorf("maxCache: %w", err) + } + cfg.MaxCachedTxs = int(mc) + } + err = s.UtxoIndexer(ctx, h, c) + if err != nil { + return fmt.Errorf("indexer: %w", err) + } + + case "txindex": + var h, c, mc uint64 + height := args["height"] + if height == "" { + // Get height from db + he, err := s.DB().MetadataGet(ctx, tbc.TxIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + return fmt.Errorf("metadata %v: %w", + string(tbc.TxIndexHeightKey), err) + } + he = make([]byte, 8) + } + h = binary.BigEndian.Uint64(he) + } else if h, err = strconv.ParseUint(height, 10, 64); err != nil { + return fmt.Errorf("height: %w", err) + } + count := args["count"] + if count == "" { + c = 0 + } else if c, err = strconv.ParseUint(count, 10, 64); err != nil { + return fmt.Errorf("count: %w", err) + } + maxCache := args["maxcache"] + if maxCache != "" { + if mc, err = strconv.ParseUint(maxCache, 10, 64); err != nil { + return fmt.Errorf("maxCache: %w", err) + } + cfg.MaxCachedTxs = int(mc) + } + err = s.TxIndexer(ctx, h, c) + if err != nil { + return fmt.Errorf("indexer: %w", err) + } + + case "blocksbytxid": + txid := args["txid"] + if txid == "" { + return fmt.Errorf("txid: must be set") + } + chtxid, err := chainhash.NewHashFromStr(txid) + if err != nil { + return fmt.Errorf("chainhash: %w", err) + } + var revTxId [32]byte + copy(revTxId[:], chtxid[:]) + + bh, err := s.DB().BlocksByTxId(ctx, revTxId) + if err != nil { + return fmt.Errorf("block by txid: %w", err) + } + for k := range bh { + fmt.Printf("%v\n", bh[k]) + } + + case "spendoutputsbytxid": + txid := args["txid"] + if txid == "" { + return fmt.Errorf("txid: must be set") + } + chtxid, err := chainhash.NewHashFromStr(txid) + if err != nil { + return fmt.Errorf("chainhash: %w", err) + } + var revTxId [32]byte + copy(revTxId[:], chtxid[:]) + + si, err := s.DB().SpendOutputsByTxId(ctx, revTxId) + if err != nil { + return fmt.Errorf("spend outputs by txid: %w", err) + } + for k := range si { + fmt.Printf("%v\n", si[k]) + } + + case "scripthashbyoutpoint": + txid := args["txid"] + if txid == "" { + return fmt.Errorf("txid: must be set") + } + chtxid, err := chainhash.NewHashFromStr(txid) + if err != nil { + return fmt.Errorf("chainhash: %w", err) + } + var revTxId [32]byte + copy(revTxId[:], chtxid[:]) + + index := args["index"] + if index == "" { + return fmt.Errorf("index: must be set") + } + idx, err := strconv.ParseUint(index, 10, 32) + if err != nil { + return fmt.Errorf("index: %w", err) + } + op := tbcd.NewOutpoint(revTxId, uint32(idx)) + sh, err := s.DB().ScriptHashByOutpoint(ctx, op) + if err != nil { + return fmt.Errorf("block by hash: %w", err) + } + spew.Dump(sh) + + case "balancebyscripthash": + address := args["address"] + hash := args["hash"] + if address == "" && hash == "" { + return fmt.Errorf("hash or address: must be set") + } else if address != "" && hash != "" { + return fmt.Errorf("hash or address: both set") + } + + var hh [32]byte + if hash != "" { + h, err := hex.DecodeString(hash) + if err != nil { + return fmt.Errorf("decode hex: %w", err) + } + copy(hh[:], h) + } + if address != "" { + // XXX set params + a, err := btcutil.DecodeAddress(address, &chaincfg.TestNet3Params) + if err != nil { + return err + } + h, err := txscript.PayToAddrScript(a) + if err != nil { + return err + } + sh := sha256.Sum256(h) + copy(hh[:], sh[:]) + } + + balance, err := s.DB().BalanceByScriptHash(ctx, hh) + if err != nil { + return fmt.Errorf("block by hash: %w", err) + } + spew.Dump(balance) + + case "utxosbyscripthash": + address := args["address"] + hash := args["hash"] + count := args["count"] + start := args["start"] + + if address == "" && hash == "" { + return fmt.Errorf("hash or address: must be set") + } else if address != "" && hash != "" { + return fmt.Errorf("hash or address: both set") + } + + if count == "" { + count = "100" + } + + if start == "" { + start = "0" + } + + countNum, err := strconv.ParseUint(count, 10, 64) + if err != nil { + return err + } + + startNum, err := strconv.ParseUint(start, 10, 64) + if err != nil { + return err + } + + var hh [32]byte + if hash != "" { + h, err := hex.DecodeString(hash) + if err != nil { + return fmt.Errorf("decode hex: %w", err) + } + copy(hh[:], h) + } + if address != "" { + // XXX set params + a, err := btcutil.DecodeAddress(address, &chaincfg.TestNet3Params) + if err != nil { + return err + } + h, err := txscript.PayToAddrScript(a) + if err != nil { + return err + } + sh := sha256.Sum256(h) + copy(hh[:], sh[:]) + } + + utxos, err := s.DB().UtxosByScriptHash(ctx, hh, startNum, countNum) + if err != nil { + return fmt.Errorf("block by hash: %w", err) + } + var balance uint64 + for k := range utxos { + fmt.Printf("%v\n", utxos[k]) + balance += utxos[k].Value() + } + fmt.Printf("utxos: %v total: %v\n", len(utxos), balance) + + default: + return fmt.Errorf("invalid action: %v", action) + } + + return nil +} + type bssClient struct { wg *sync.WaitGroup bssURL string @@ -187,7 +699,7 @@ func (bsc *bssClient) connect(ctx context.Context) error { // Timestamp: time.Now().Unix(), // }) // if err != nil { - // return fmt.Errorf("ping error: %v", err) + // return fmt.Errorf("ping error: %w", err) // } simulatePingPong := false @@ -210,7 +722,7 @@ func (bsc *bssClient) connect(ctx context.Context) error { if err != nil { log.Errorf("ping error: %v", err) continue - // return fmt.Errorf("ping error: %v", err) + // return fmt.Errorf("ping error: %w", err) } } }() @@ -255,7 +767,7 @@ func bssLong(ctx context.Context) error { go bsc.connectBSS(ctx) <-ctx.Done() - if context.Canceled != ctx.Err() && ctx.Err() != context.Canceled { + if !errors.Is(ctx.Err(), context.Canceled) { return ctx.Err() } @@ -264,7 +776,7 @@ func bssLong(ctx context.Context) error { func client(which string) error { log.Debugf("client %v", which) - defer log.Debugf("client exit", which) + defer log.Debugf("client %v exit", which) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -304,6 +816,9 @@ func init() { for k, v := range bfgapi.APICommands() { allCommands[string(k)] = v } + for k, v := range tbcapi.APICommands() { + allCommands[string(k)] = v + } sortedCommands = make([]string, 0, len(allCommands)) for k := range allCommands { @@ -320,6 +835,7 @@ func usage() { fmt.Fprintf(os.Stderr, "\tbss-client long connection to bss\n") fmt.Fprintf(os.Stderr, "\thelp (this help)\n") fmt.Fprintf(os.Stderr, "\thelp-verbose JSON print RPC default request/response\n") + fmt.Fprintf(os.Stderr, "\ttbcdb datase open (tbcd must not be running)\n") fmt.Fprintf(os.Stderr, "Environment:\n") config.Help(os.Stderr, cm) fmt.Fprintf(os.Stderr, "Commands:\n") @@ -388,6 +904,8 @@ func _main() error { case "help-verbose": helpVerbose() return nil + case "tbcdb": + return tbcdb() } // Deal with generic commands @@ -410,6 +928,10 @@ func _main() error { u = bfgapi.DefaultPrivateURL callHandler = handleBFGWebsocketReadUnauth call = bfgapi.Call // XXX yuck + case strings.HasPrefix(cmd, "tbcapi"): + u = tbcapi.DefaultURL + callHandler = handleTBCWebsocketRead + call = tbcapi.Call // XXX yuck? default: return fmt.Errorf("can't derive URL from command: %v", cmd) } diff --git a/cmd/keygen/keygen.go b/cmd/keygen/keygen.go index 70f3666b7dbb..57321273c987 100644 --- a/cmd/keygen/keygen.go +++ b/cmd/keygen/keygen.go @@ -48,7 +48,7 @@ func _main() error { case *secp256k1KeyPair: privKey, err := dcrsecpk256k1.GeneratePrivateKey() if err != nil { - return fmt.Errorf("Failed to generate secp256k1 private key: %v", err) + return fmt.Errorf("failed to generate secp256k1 private key: %w", err) } btcAddress, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), btcChainParams) @@ -75,7 +75,7 @@ func _main() error { } js, err := json.MarshalIndent(s, "", " ") if err != nil { - return fmt.Errorf("marshal: %v", err) + return fmt.Errorf("marshal: %w", err) } fmt.Printf("%s\n", js) } else { diff --git a/cmd/popmd/popmd.go b/cmd/popmd/popmd.go index 32c5d30084a1..e38c50c7999c 100644 --- a/cmd/popmd/popmd.go +++ b/cmd/popmd/popmd.go @@ -6,6 +6,7 @@ package main import ( "context" + "errors" "fmt" "os" "os/signal" @@ -59,6 +60,12 @@ var ( Help: "address and port bssd prometheus listens on", Print: config.PrintAll, }, + "POPM_REMINE_THRESHOLD": config.Config{ + Value: &cfg.RetryMineThreshold, + DefaultValue: uint(0), + Help: "the number of L2 Keystones behind the latest seen that we are willing to remine, this is handy for re-orgs", + Print: config.PrintAll, + }, } ) @@ -103,10 +110,10 @@ func _main() error { miner, err := popm.NewMiner(cfg) if err != nil { - return fmt.Errorf("Failed to create POP miner: %v", err) + return fmt.Errorf("failed to create POP miner: %w", err) } - if err := miner.Run(ctx); err != context.Canceled { - return fmt.Errorf("POP miner terminated: %v", err) + if err := miner.Run(ctx); !errors.Is(err, context.Canceled) { + return fmt.Errorf("POP miner terminated: %w", err) } return nil diff --git a/cmd/tbcd/README.md b/cmd/tbcd/README.md new file mode 100644 index 000000000000..a529863a7e6a --- /dev/null +++ b/cmd/tbcd/README.md @@ -0,0 +1,56 @@ +# tbcd + +## Hemi Tiny Bitcoin Daemon + +tbcd is a very minimal bitcoin block downloader and indexer meant for embedding in other applications that require access to bitcoin data (blocks and txes). + +tbcd requires sufficient disk space for a full download of bitcoin block data on a fast (preferably ssd or better disk. + +tbcd is build with the heminetwork makefile, To build standalone (requires `go 1.21+`), type: + +``` sh +cd heminetowkr/cmd/tbcd +go build +``` + +On some linux systems you may need to increase the number of open files allowed (particularly with slower disks) and the maximum stack size. If you run into open file or OOM errors, in the shell you are going to run tbcd, run: + +```sh +ulimit -n 8192 +ulimit -s 8192 +``` + +You can confirm these settings wiht: + +```sh +ulimit -a +``` + +For a full list of options: + +``` sh +./bin/tbcd --help +``` + +You can change the file storage with: + +``` sh +export TBC_LEVELDB_HOME=/path/to/files +``` + +Specify the network with + +``` sh +export TBC_NETWORK=mainnet +``` + +Then run with: + +``` sh +./bin/tbcd +``` + +### License + +This project is licensed under the [MIT License](../../LICENSE). + diff --git a/cmd/tbcd/tbcd.go b/cmd/tbcd/tbcd.go new file mode 100644 index 000000000000..ceb585063fd1 --- /dev/null +++ b/cmd/tbcd/tbcd.go @@ -0,0 +1,178 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package main + +import ( + "context" + "fmt" + "os" + "os/signal" + + "github.com/juju/loggo" + + "github.com/hemilabs/heminetwork/api/tbcapi" + "github.com/hemilabs/heminetwork/config" + "github.com/hemilabs/heminetwork/service/tbc" + "github.com/hemilabs/heminetwork/version" +) + +const ( + daemonName = "tbcd" + defaultLogLevel = daemonName + "=INFO;tbc=INFO;level=INFO" + defaultNetwork = "testnet3" // XXX make this mainnet + defaultHome = "~/." + daemonName +) + +var ( + log = loggo.GetLogger(daemonName) + welcome = fmt.Sprintf("Hemi Tiny Bitcoin Daemon: v%v", version.String()) + + cfg = tbc.NewDefaultConfig() + cm = config.CfgMap{ + "TBC_ADDRESS": config.Config{ + Value: &cfg.ListenAddress, + DefaultValue: tbcapi.DefaultListen, + Help: "address port to listen on", + Print: config.PrintAll, + }, + "TBC_AUTO_INDEX": config.Config{ + Value: &cfg.AutoIndex, + DefaultValue: true, + Help: "enable auto utxo and tx indexes", + Print: config.PrintAll, + }, + "TBC_BLOCK_SANITY": config.Config{ + Value: &cfg.BlockSanity, + DefaultValue: false, + Help: "enable/disable block sanity checks before inserting", + Print: config.PrintAll, + }, + "TBC_LEVELDB_HOME": config.Config{ + Value: &cfg.LevelDBHome, + DefaultValue: defaultHome, + Help: "data directory for leveldb", + Print: config.PrintAll, + }, + "TBC_LOG_LEVEL": config.Config{ + Value: &cfg.LogLevel, + DefaultValue: defaultLogLevel, + Help: "loglevel for various packages; INFO, DEBUG and TRACE", + Print: config.PrintAll, + }, + "TBC_MAX_CACHED_TXS": config.Config{ + Value: &cfg.MaxCachedTxs, + DefaultValue: 1000000, + Help: "maximum cached utxos and/or txs during indexing", + Print: config.PrintAll, + }, + "TBC_NETWORK": config.Config{ + Value: &cfg.Network, + DefaultValue: defaultNetwork, + Help: "bitcoin network; mainnet or testnet3", + Print: config.PrintAll, + }, + "TBC_PROMETHEUS_ADDRESS": config.Config{ + Value: &cfg.PrometheusListenAddress, + DefaultValue: "", + Help: "address and port tbcd prometheus listens on", + Print: config.PrintAll, + }, + } +) + +func HandleSignals(ctx context.Context, cancel context.CancelFunc, callback func(os.Signal)) { + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt) + signal.Notify(signalChan, os.Kill) + defer func() { + signal.Stop(signalChan) + cancel() + }() + + select { + case <-ctx.Done(): + case s := <-signalChan: // First signal, cancel context. + if callback != nil { + callback(s) // Do whatever caller wants first. + cancel() + } + } + <-signalChan // Second signal, hard exit. + os.Exit(2) +} + +func _main() error { + // Parse configuration from environment + if err := config.Parse(cm); err != nil { + return err + } + + loggo.ConfigureLoggers(cfg.LogLevel) + log.Infof("%v", welcome) + + pc := config.PrintableConfig(cm) + for k := range pc { + log.Infof("%v", pc[k]) + } + + ctx, cancel := context.WithCancel(context.Background()) + go HandleSignals(ctx, cancel, func(s os.Signal) { + log.Infof("tbc service received signal: %s", s) + }) + + server, err := tbc.NewServer(cfg) + if err != nil { + return fmt.Errorf("Failed to create tbc server: %v", err) + } + // XXX remove, this is an illustration of calling the direct API of server + // go func() { + // for { + // select { + // case <-ctx.Done(): + // return + // case <-time.After(2 * time.Second): + // } + + // log.Infof("synced: %v", spew.Sdump(server.Synced(ctx))) + // hashS := "000000001a4c2c64beded987790ab0c00675b4bc467cd3574ad455b1397c967c" + // ch, err := chainhash.NewHashFromStr(hashS) + // if err != nil { + // panic(err) + // } + // bh, height, err := server.BlockHeaderByHash(ctx, ch) + // if err != nil { + // panic(err) + // } + // log.Infof("height %v hash %v%v", height, bh.BlockHash(), spew.Sdump(bh)) + + // bhbh, err := server.BlockHeadersByHeight(ctx, height) + // if err != nil { + // panic(err) + // } + // log.Infof("height %v headers %v", height, spew.Sdump(bhbh)) + // } + //}() + if err := server.Run(ctx); err != context.Canceled { + return fmt.Errorf("tbc server terminated: %v", err) + } + + return nil +} + +func main() { + if len(os.Args) != 1 { + fmt.Fprintf(os.Stderr, "%v\n", welcome) + fmt.Fprintf(os.Stderr, "Usage:\n") + fmt.Fprintf(os.Stderr, "\thelp (this help)\n") + fmt.Fprintf(os.Stderr, "Environment:\n") + config.Help(os.Stderr, cm) + os.Exit(1) + } + + if err := _main(); err != nil { + log.Errorf("%v", err) + os.Exit(1) + } +} diff --git a/config/config.go b/config/config.go index ccf145acc589..d4012c6bfc0e 100644 --- a/config/config.go +++ b/config/config.go @@ -37,11 +37,11 @@ func Parse(c CfgMap) error { for k, v := range c { // Make sure v.Value is a pointer if reflect.TypeOf(v.Value).Kind() != reflect.Pointer { - return fmt.Errorf("Value must be a pointer") + return fmt.Errorf("value must be a pointer") } // Make sure we are pointing to the same type if reflect.TypeOf(v.Value).Elem() != reflect.TypeOf(v.DefaultValue) { - return fmt.Errorf("Value not the same type as DefaultValue, "+ + return fmt.Errorf("value not the same type as DefaultValue, "+ "wanted %v got %v", reflect.TypeOf(v.Value).Elem(), reflect.TypeOf(v.DefaultValue)) } diff --git a/database/bfgd/postgres/postgres.go b/database/bfgd/postgres/postgres.go index fe160b9b1e8c..043d062f4838 100644 --- a/database/bfgd/postgres/postgres.go +++ b/database/bfgd/postgres/postgres.go @@ -124,7 +124,7 @@ func (p *pgdb) L2KeystonesInsert(ctx context.Context, l2ks []bfgd.L2Keystone) er defer func() { err := tx.Rollback() - if err != nil && err != sql.ErrTxDone { + if err != nil && !errors.Is(err, sql.ErrTxDone) { log.Errorf("L2KeystonesInsert could not rollback db tx: %v", err) return @@ -164,11 +164,11 @@ func (p *pgdb) L2KeystonesInsert(ctx context.Context, l2ks []bfgd.L2Keystone) er log.Errorf("integrity violation occurred: %s", err.Constraint) return database.DuplicateError(fmt.Sprintf("constraint error: %s", err)) } - return fmt.Errorf("failed to insert l2 keystone: %v", err) + return fmt.Errorf("failed to insert l2 keystone: %w", err) } rows, err := result.RowsAffected() if err != nil { - return fmt.Errorf("failed to insert l2 keystone rows affected: %v", err) + return fmt.Errorf("failed to insert l2 keystone rows affected: %w", err) } if rows < 1 { return fmt.Errorf("failed to insert l2 keystone rows: %v", rows) @@ -210,7 +210,7 @@ func (p *pgdb) L2KeystoneByAbrevHash(ctx context.Context, aHash [32]byte) (*bfgd &l2ks.ParentEPHash, &l2ks.PrevKeystoneEPHash, &l2ks.StateRoot, &l2ks.EPHash, &l2ks.Version, &l2ks.CreatedAt, &l2ks.UpdatedAt, ); err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, database.NotFoundError("l2 keystone not found") } return nil, err @@ -257,7 +257,7 @@ func (p *pgdb) L2KeystonesMostRecentN(ctx context.Context, n uint32) ([]bfgd.L2K &k.ParentEPHash, &k.PrevKeystoneEPHash, &k.StateRoot, &k.EPHash, &k.Version, &k.CreatedAt, &k.UpdatedAt, ); err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, database.NotFoundError("pop data not found") } return nil, err @@ -275,6 +275,7 @@ func (p *pgdb) L2KeystonesMostRecentN(ctx context.Context, n uint32) ([]bfgd.L2K func (p *pgdb) BtcBlockInsert(ctx context.Context, bb *bfgd.BtcBlock) error { log.Tracef("BtcBlockInsert") defer log.Tracef("BtcBlockInsert exit") + const qBtcBlockInsert = ` INSERT INTO btc_blocks (hash, header, height) VALUES ($1, $2, $3) @@ -285,11 +286,11 @@ func (p *pgdb) BtcBlockInsert(ctx context.Context, bb *bfgd.BtcBlock) error { if err, ok := err.(*pq.Error); ok && err.Code.Class().Name() == "integrity_constraint_violation" { return database.DuplicateError(fmt.Sprintf("duplicate btc block entry: %s", err)) } - return fmt.Errorf("failed to insert btc block: %v", err) + return fmt.Errorf("failed to insert btc block: %w", err) } rows, err := result.RowsAffected() if err != nil { - return fmt.Errorf("failed to insert btc block rows affected: %v", err) + return fmt.Errorf("failed to insert btc block rows affected: %w", err) } if rows < 1 { return fmt.Errorf("failed to insert btc block rows: %v", rows) @@ -312,7 +313,7 @@ func (p *pgdb) BtcBlockByHash(ctx context.Context, hash [32]byte) (*bfgd.BtcBloc row := p.db.QueryRowContext(ctx, q, hash[:]) if err := row.Scan(&bb.Hash, &bb.Header, &bb.Height, &bb.CreatedAt, &bb.UpdatedAt); err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, database.NotFoundError("btc block not found") } return nil, err @@ -333,7 +334,7 @@ func (p *pgdb) BtcBlockHeightByHash(ctx context.Context, hash [32]byte) (uint64, var height uint64 row := p.db.QueryRowContext(ctx, q, hash[:]) if err := row.Scan(&height); err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return 0, database.NotFoundError("btc block height not found") } return 0, err @@ -364,11 +365,11 @@ func (p *pgdb) PopBasisInsertPopMFields(ctx context.Context, pb *bfgd.PopBasis) return database.DuplicateError(fmt.Sprintf("duplicate pop block entry: %s", err.Error())) } } - return fmt.Errorf("failed to insert pop block: %v", err) + return fmt.Errorf("failed to insert pop block: %w", err) } rows, err := result.RowsAffected() if err != nil { - return fmt.Errorf("failed to insert pop block rows affected: %v", err) + return fmt.Errorf("failed to insert pop block rows affected: %w", err) } if rows < 1 { return fmt.Errorf("failed to insert pop block rows: %v", rows) @@ -416,12 +417,12 @@ func (p *pgdb) PopBasisUpdateBTCFields(ctx context.Context, pb *bfgd.PopBasis) ( return 0, database.DuplicateError(fmt.Sprintf("duplicate pop block entry: %s", err.Error())) } } - return 0, fmt.Errorf("failed to insert pop block: %v", err) + return 0, fmt.Errorf("failed to insert pop block: %w", err) } rows, err := result.RowsAffected() if err != nil { - return 0, fmt.Errorf("failed to insert pop block rows affected: %v", err) + return 0, fmt.Errorf("failed to insert pop block rows affected: %w", err) } return rows, nil @@ -464,11 +465,11 @@ func (p *pgdb) PopBasisInsertFull(ctx context.Context, pb *bfgd.PopBasis) error return database.DuplicateError(fmt.Sprintf("duplicate pop block entry: %s", err.Error())) } } - return fmt.Errorf("failed to insert pop block: %v", err) + return fmt.Errorf("failed to insert pop block: %w", err) } rows, err := result.RowsAffected() if err != nil { - return fmt.Errorf("failed to insert pop block rows affected: %v", err) + return fmt.Errorf("failed to insert pop block rows affected: %w", err) } if rows < 1 { return fmt.Errorf("failed to insert pop block rows: %v", rows) diff --git a/database/bfgd/scripts/0001.sql b/database/bfgd/scripts/0001.sql index f7796c9596fe..fcfebb6d08a6 100644 --- a/database/bfgd/scripts/0001.sql +++ b/database/bfgd/scripts/0001.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; -- Create database version diff --git a/database/bfgd/scripts/0002.sql b/database/bfgd/scripts/0002.sql index cf52cafe6b22..a3650f164a0b 100644 --- a/database/bfgd/scripts/0002.sql +++ b/database/bfgd/scripts/0002.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; UPDATE version SET version = 2; diff --git a/database/bfgd/scripts/0003.sql b/database/bfgd/scripts/0003.sql index d8430b571a86..e9bfe25cd8e6 100644 --- a/database/bfgd/scripts/0003.sql +++ b/database/bfgd/scripts/0003.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; UPDATE version SET version = 3; diff --git a/database/bfgd/scripts/0004.sql b/database/bfgd/scripts/0004.sql index bd29efe695c7..41c31477654c 100644 --- a/database/bfgd/scripts/0004.sql +++ b/database/bfgd/scripts/0004.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; UPDATE version SET version = 4; diff --git a/database/bfgd/scripts/0005.sql b/database/bfgd/scripts/0005.sql index a5c02e74ef8f..77cc5101599d 100644 --- a/database/bfgd/scripts/0005.sql +++ b/database/bfgd/scripts/0005.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; UPDATE version SET version = 5; diff --git a/database/bfgd/scripts/0006.sql b/database/bfgd/scripts/0006.sql index bffeb0dca081..9ec3c67b5d44 100644 --- a/database/bfgd/scripts/0006.sql +++ b/database/bfgd/scripts/0006.sql @@ -1,3 +1,7 @@ +-- Copyright (c) 2024 Hemi Labs, Inc. +-- Use of this source code is governed by the MIT License, +-- which can be found in the LICENSE file. + BEGIN; UPDATE version SET version = 6; diff --git a/database/database.go b/database/database.go index 5e61a65394f9..a77df1f12d8b 100644 --- a/database/database.go +++ b/database/database.go @@ -57,10 +57,22 @@ func (ve ValidationError) Is(target error) bool { return ok } +type ZeroRowsError string + +func (ze ZeroRowsError) Error() string { + return string(ze) +} + +func (ze ZeroRowsError) Is(target error) bool { + _, ok := target.(ZeroRowsError) + return ok +} + var ( ErrDuplicate = DuplicateError("duplicate") ErrNotFound = NotFoundError("not found") ErrValidation = ValidationError("validation") + ErrZeroRows = ZeroRowsError("zero rows affected") ) // ByteArray is a type that corresponds to BYTEA in a database. It supports @@ -72,11 +84,11 @@ func (ba ByteArray) String() string { return hex.EncodeToString([]byte(ba)) } -func (ba *ByteArray) MarshalJSON() ([]byte, error) { - if *ba == nil { +func (ba ByteArray) MarshalJSON() ([]byte, error) { + if ba == nil { return []byte("null"), nil } - return []byte(fmt.Sprintf("\"\\\\x%s\"", hex.EncodeToString([]byte(*ba)))), nil + return []byte(fmt.Sprintf("\"\\\\x%s\"", hex.EncodeToString([]byte(ba)))), nil } func (ba *ByteArray) UnmarshalJSON(data []byte) error { @@ -119,10 +131,10 @@ func (ba ByteArray) Value() (driver.Value, error) { return []byte(ba), nil } -//// XXX figure out why this doens't work -//func (ba *ByteArray) Value() (driver.Value, error) { +// // XXX figure out why this doens't work +// func (ba *ByteArray) Value() (driver.Value, error) { // return *ba, nil -//} +// } var _ driver.Valuer = (*ByteArray)(nil) @@ -156,7 +168,7 @@ func (bi *BigInt) SetUint64(val uint64) *BigInt { return bi } -func (bi *BigInt) MarshalJSON() ([]byte, error) { +func (bi BigInt) MarshalJSON() ([]byte, error) { if bi.Int == nil { return []byte("null"), nil } @@ -214,9 +226,8 @@ type Timestamp struct { const timestampFormat = `2006-01-02T15:04:05.999999999` -// NewTimestamp returns a Timestamp initialized with the given time. func NewTimestamp(time time.Time) Timestamp { - return Timestamp{Time: time} + return Timestamp{Time: time.Round(0).UTC()} } func (ts Timestamp) MarshalJSON() ([]byte, error) { @@ -320,7 +331,7 @@ func (tz *TimeZone) UnmarshalJSON(data []byte) error { return nil } if err := tz.Parse(s); err != nil { - return fmt.Errorf("invalid timezone: %v", err) + return fmt.Errorf("invalid timezone: %w", err) } return nil } @@ -335,7 +346,7 @@ func (tz *TimeZone) Scan(value interface{}) error { return fmt.Errorf("not a string (%T)", value) } if err := tz.Parse(s); err != nil { - return fmt.Errorf("invalid timezone: %v", err) + return fmt.Errorf("invalid timezone: %w", err) } return nil } diff --git a/database/database_test.go b/database/database_test.go index afd131978a04..80b5ce2a4e23 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -6,11 +6,42 @@ package database import ( "bytes" + "encoding/json" "fmt" + "reflect" "testing" "time" + + "github.com/davecgh/go-spew/spew" ) +func TestStructByteArrayJSON(t *testing.T) { + type X struct { + Y BigInt + Ts Timestamp + MyByteArray ByteArray + } + + y := NewBigIntZero().SetUint64(15) + x := X{ + Y: *y, + Ts: NewTimestamp(time.Now()), + MyByteArray: []byte{0x01, 0x02}, + } + jx, err := json.Marshal(x) + if err != nil { + t.Fatal(err) + } + var xx X + err = json.Unmarshal(jx, &xx) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(x, xx) { + t.Fatalf("not equal %v%v", spew.Sdump(x), spew.Sdump(xx)) + } +} + func TestByteArrayJSON(t *testing.T) { tests := []struct { data []byte diff --git a/database/level/level.go b/database/level/level.go new file mode 100644 index 000000000000..f226b2a79746 --- /dev/null +++ b/database/level/level.go @@ -0,0 +1,211 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package level + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "sync" + + "github.com/juju/loggo" + "github.com/mitchellh/go-homedir" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/opt" + + "github.com/hemilabs/heminetwork/database" +) + +const ( + logLevel = "INFO" + + BlockHeadersDB = "blockheaders" + BlocksMissingDB = "blocksmissing" + BlocksDB = "blocks" + MetadataDB = "metadata" + HeightHashDB = "heighthash" + PeersDB = "peers" + OutputsDB = "outputs" + TransactionsDB = "transactions" + + versionKey = "version" + databaseVersion = 1 +) + +var log = loggo.GetLogger("level") + +func init() { + loggo.ConfigureLoggers(logLevel) +} + +type ( + Pool map[string]*leveldb.DB + Database struct { + mtx sync.RWMutex + wg sync.WaitGroup // Wait group for notification handler exit + + pool Pool // database pool + + ntfn map[database.NotificationName]int // Notification handlers + home string // leveld toplevel database directory + } +) + +var _ database.Database = (*Database)(nil) + +func (l *Database) Close() error { + log.Tracef("Close") + defer log.Tracef("Close exit") + + l.mtx.Lock() + defer l.mtx.Unlock() + + var errSeen error // XXX return last error for now + for k, v := range l.pool { + err := v.Close() + if err != nil { + // do continue, leveldb does not like unfresh shutdowns + log.Errorf("close %v: %v", k, err) + errSeen = err + } + } + + return errSeen +} + +func (l *Database) DB() Pool { + log.Tracef("DB") + defer log.Tracef("DB exit") + + return l.pool +} + +func (l *Database) RegisterNotification(ctx context.Context, n database.NotificationName, f database.NotificationCallback, payload any) error { + log.Tracef("RegisterNotification") + defer log.Tracef("RegisterNotification exit") + + return fmt.Errorf("RegisterNotification") +} + +func (l *Database) UnregisterNotification(n database.NotificationName) error { + log.Tracef("UnregisterNotification") + defer log.Tracef("UnregisterNotification exit") + + return fmt.Errorf("UnregisterNotification") +} + +func (l *Database) openDB(name string, options *opt.Options) error { + l.mtx.Lock() + defer l.mtx.Unlock() + + bhs := filepath.Join(l.home, name) + bhsDB, err := leveldb.OpenFile(bhs, options) + if err != nil { + return fmt.Errorf("leveldb open %v: %w", name, err) + } + l.pool[name] = bhsDB + + return nil +} + +func (l *Database) Version(ctx context.Context) (int, error) { + mdDB := l.pool[MetadataDB] + value, err := mdDB.Get([]byte(versionKey), nil) + if err != nil { + return -1, fmt.Errorf("version: %w", err) + } + var dbVersion uint64 + dbVersion = binary.BigEndian.Uint64(value) + + return int(dbVersion), nil +} + +func New(ctx context.Context, home string, version int) (*Database, error) { + log.Tracef("New") + defer log.Tracef("New exit") + + h, err := homedir.Expand(home) + if err != nil { + return nil, fmt.Errorf("home dir: %w", err) + } + err = os.MkdirAll(h, 0o0700) + if err != nil { + return nil, fmt.Errorf("mkdir: %w", err) + } + + l := &Database{ + home: h, + pool: make(Pool), + } + + unwind := true + defer func() { + if unwind { + log.Errorf("new unwind exited with: %v", l.Close()) + } + }() + + // Peers table + err = l.openDB(BlockHeadersDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", BlockHeadersDB, err) + } + err = l.openDB(BlocksDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", BlocksDB, err) + } + err = l.openDB(BlocksMissingDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", BlocksMissingDB, err) + } + err = l.openDB(HeightHashDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", HeightHashDB, err) + } + err = l.openDB(PeersDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", PeersDB, err) + } + err = l.openDB(OutputsDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", OutputsDB, err) + } + err = l.openDB(TransactionsDB, nil) + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", TransactionsDB, err) + } + + // Treat metadata special so that we can insert some stuff. + err = l.openDB(MetadataDB, &opt.Options{ErrorIfMissing: true}) + if errors.Is(err, fs.ErrNotExist) { + err = l.openDB(MetadataDB, &opt.Options{ErrorIfMissing: false}) + if err != nil { + return nil, fmt.Errorf("leveldb initial %v: %w", MetadataDB, err) + } + versionData := make([]byte, 8) + binary.BigEndian.PutUint64(versionData, databaseVersion) + err = l.pool[MetadataDB].Put([]byte(versionKey), versionData, nil) + } + // Check metadata error + if err != nil { + return nil, fmt.Errorf("leveldb %v: %w", MetadataDB, err) + } + dbVersion, err := l.Version(ctx) + if err != nil { + return nil, err + } + if dbVersion != version { + return nil, fmt.Errorf("invalid version: wanted %v got %v", + dbVersion, version) + } + + unwind = false + + return l, nil +} diff --git a/database/postgres/postgres.go b/database/postgres/postgres.go index 2cf5e97edd4e..7e4f8daed4a8 100644 --- a/database/postgres/postgres.go +++ b/database/postgres/postgres.go @@ -50,14 +50,16 @@ type Database struct { pool *sql.DB } +var _ database.Database = (*Database)(nil) + // Connect connects to a postgres database. This is only used in tests. func Connect(ctx context.Context, uri string) (*sql.DB, error) { pool, err := sql.Open("postgres", uri) if err != nil { - return nil, fmt.Errorf("postgres open: %v", err) + return nil, fmt.Errorf("postgres open: %w", err) } if err := pool.PingContext(ctx); err != nil { - return nil, fmt.Errorf("unable to connect to database: %v", err) + return nil, fmt.Errorf("unable to connect to database: %w", err) } return pool, nil } @@ -256,13 +258,13 @@ func New(ctx context.Context, puri string, version int) (*Database, error) { // Setup and connect to database. pool, err := sql.Open("postgres", puri) if err != nil { - return nil, fmt.Errorf("postgres open: %v", err) + return nil, fmt.Errorf("postgres open: %w", err) } pool.SetConnMaxLifetime(0) pool.SetMaxIdleConns(5) pool.SetMaxOpenConns(5) if err := pool.PingContext(ctx); err != nil { - return nil, fmt.Errorf("unable to connect to database: %v", err) + return nil, fmt.Errorf("unable to connect to database: %w", err) } // Verify version. diff --git a/database/tbcd/TESTS.md b/database/tbcd/TESTS.md new file mode 100644 index 000000000000..f7d9962b8351 --- /dev/null +++ b/database/tbcd/TESTS.md @@ -0,0 +1,11 @@ +## Running extended tests + +Create a user that has CREATEDB privilege. +``` +sudo -u postgres psql -c "CREATE ROLE tbcdtest WITH LOGIN PASSWORD 'password' NOSUPERUSER CREATEDB;" +``` + +run tests: +``` +PGTESTURI="postgres://tbcdtest:password@localhost/postgres" go test -v ./... +``` diff --git a/database/tbcd/database.go b/database/tbcd/database.go new file mode 100644 index 000000000000..5375e20b3951 --- /dev/null +++ b/database/tbcd/database.go @@ -0,0 +1,371 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbcd + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/hex" + "fmt" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + + "github.com/hemilabs/heminetwork/database" +) + +type Database interface { + database.Database + + // Metadata + Version(ctx context.Context) (int, error) + MetadataGet(ctx context.Context, key []byte) ([]byte, error) + MetadataPut(ctx context.Context, key, value []byte) error + + // Block header + BlockHeaderByHash(ctx context.Context, hash []byte) (*BlockHeader, error) + BlockHeadersBest(ctx context.Context) ([]BlockHeader, error) + BlockHeadersByHeight(ctx context.Context, height uint64) ([]BlockHeader, error) + BlockHeadersInsert(ctx context.Context, bhs []BlockHeader) error + + // Block + BlocksMissing(ctx context.Context, count int) ([]BlockIdentifier, error) + BlockInsert(ctx context.Context, b *Block) (int64, error) + // XXX replace BlockInsert with plural version + // BlocksInsert(ctx context.Context, bs []*Block) (int64, error) + BlockByHash(ctx context.Context, hash []byte) (*Block, error) + + // Transactions + BlockUtxoUpdate(ctx context.Context, utxos map[Outpoint]CacheOutput) error + BlockTxUpdate(ctx context.Context, txs map[TxKey]*TxValue) error + BlocksByTxId(ctx context.Context, txId TxId) ([]BlockHash, error) + SpendOutputsByTxId(ctx context.Context, txId TxId) ([]SpendInfo, error) + + // Peer manager + PeersStats(ctx context.Context) (int, int) // good, bad count + PeersInsert(ctx context.Context, peers []Peer) error // insert or update + PeerDelete(ctx context.Context, host, port string) error // remove peer + PeersRandom(ctx context.Context, count int) ([]Peer, error) + + // ScriptHash returns the sha256 of PkScript for the provided outpoint. + BalanceByScriptHash(ctx context.Context, sh ScriptHash) (uint64, error) + ScriptHashByOutpoint(ctx context.Context, op Outpoint) (*ScriptHash, error) + UtxosByScriptHash(ctx context.Context, sh ScriptHash, start uint64, count uint64) ([]Utxo, error) +} + +// BlockHeader contains the first 80 raw bytes of a bitcoin block and its +// location information (hash+height). +type BlockHeader struct { + Hash database.ByteArray + Height uint64 + Header database.ByteArray +} + +func (bh BlockHeader) String() string { + ch, _ := chainhash.NewHash(bh.Hash) + return ch.String() +} + +func (bh BlockHeader) Timestamp() time.Time { + var wbh wire.BlockHeader + err := wbh.Deserialize(bytes.NewReader(bh.Header)) + if err != nil { + return time.Time{} + } + return wbh.Timestamp +} + +func (bh BlockHeader) Wire() (*wire.BlockHeader, error) { + var wbh wire.BlockHeader + err := wbh.Deserialize(bytes.NewReader(bh.Header)) + if err != nil { + return nil, fmt.Errorf("deserialize: %w", err) + } + return &wbh, nil +} + +// Block contains a raw bitcoin block and its corresponding hash. +type Block struct { + Hash database.ByteArray + Block database.ByteArray +} + +// BlockIdentifier uniquely identifies a block using it's hash and height. +type BlockIdentifier struct { + Height uint64 + Hash database.ByteArray +} + +type SpendInfo struct { + BlockHash BlockHash + TxId TxId + InputIndex uint32 +} + +// Peer +type Peer struct { + Host string + Port string + LastAt database.Timestamp `deep:"-"` // Last time connected + CreatedAt database.Timestamp `deep:"-"` +} + +// XXX we can probably save a bunch of bcopy if we construct the key directly +// for the db. Peek at the s + t cache which does this. + +// Outpoint is a bitcoin structure that points to a transaction in a block. It +// is expressed as an array of bytes in order to pack it as dense as possible +// for memory conservation reasons. +type Outpoint [37]byte // Outpoint Tx id + +// String returns a reversed pretty printed outpoint. +func (o Outpoint) String() string { + hash, _ := chainhash.NewHash(o[1:33]) + return fmt.Sprintf("%s:%d", hash, binary.BigEndian.Uint32(o[33:])) +} + +func (o Outpoint) TxId() []byte { + return o[1:33] +} + +func (o Outpoint) TxIndex() uint32 { + return binary.BigEndian.Uint32(o[33:]) +} + +func (o Outpoint) TxIndexBytes() []byte { + return o[33:] +} + +func NewOutpoint(txid [32]byte, index uint32) (op Outpoint) { + op[0] = 'u' // match leveldb cache so that we preven a bunch of bcopy + copy(op[1:33], txid[:]) + binary.BigEndian.PutUint32(op[33:], index) + return +} + +// CacheOutput is a densely packed representation of a bitcoin UTXo. The fields are +// script_hash + value + out_index. It is packed for +// memory conservation reasons. +type CacheOutput [32 + 8 + 4]byte // script_hash + value + out_idx + +// String reutrns pretty printable CacheOutput. Hash is not reversed since it is an +// opaque pointer. It prints satoshis@script_hash:output_index +func (c CacheOutput) String() string { + return fmt.Sprintf("%d @ %v:%d", binary.BigEndian.Uint64(c[32:40]), + c[0:32], binary.BigEndian.Uint32(c[40:])) +} + +func (c CacheOutput) ScriptHash() (hash [32]byte) { + copy(hash[:], c[0:32]) + return +} + +func (c CacheOutput) ScriptHashSlice() []byte { + return c[0:32] +} + +func (c CacheOutput) Value() uint64 { + return binary.BigEndian.Uint64(c[32:40]) +} + +func (c CacheOutput) ValueBytes() []byte { + return c[32:40] +} + +func (c CacheOutput) OutputIndex() uint32 { + return binary.BigEndian.Uint32(c[40:]) +} + +func (c CacheOutput) OutputIndexBytes() []byte { + return c[40:44] +} + +func (c CacheOutput) Equal(x CacheOutput) bool { + return bytes.Equal(c[:], x[:]) +} + +// DeleteUtxo is the max uint64 value which is used as a sentinel to indicate +// that a utxo should be reaped. The remaining fields must remain untouched +// since they are part of the lookup key of the utxo balance. +var DeleteUtxo = [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +func (c CacheOutput) IsDelete() bool { + return bytes.Equal(c[32:40], DeleteUtxo[:]) +} + +func NewCacheOutput(hash [32]byte, value uint64, outIndex uint32) (co CacheOutput) { + copy(co[0:32], hash[:]) // scripthash + binary.BigEndian.PutUint64(co[32:40], value) + binary.BigEndian.PutUint32(co[40:], outIndex) + return +} + +func NewDeleteCacheOutput(hash [32]byte, outIndex uint32) (co CacheOutput) { + copy(co[0:32], hash[:]) // scripthash or txid + copy(co[32:40], DeleteUtxo[:]) + binary.BigEndian.PutUint32(co[40:], outIndex) + return +} + +// Utxo packs a transaction id, the value and the out index. +type Utxo [32 + 8 + 4]byte // tx_id + value + out_idx + +// String reutrns pretty printable CacheOutput. Hash is not reversed since it is an +// opaque pointer. It prints satoshis@script_hash:output_index +func (u Utxo) String() string { + ch, _ := chainhash.NewHash(u[0:32]) + return fmt.Sprintf("%d @ %v:%d", binary.BigEndian.Uint64(u[32:40]), + ch, binary.BigEndian.Uint32(u[40:])) +} + +func (u Utxo) ScriptHash() (hash [32]byte) { + copy(hash[:], u[0:32]) + return +} + +func (u Utxo) ScriptHashSlice() []byte { + return u[0:32] +} + +func (u Utxo) Value() uint64 { + return binary.BigEndian.Uint64(u[32:40]) +} + +func (u Utxo) ValueBytes() []byte { + return u[32:40] +} + +func (u Utxo) OutputIndex() uint32 { + return binary.BigEndian.Uint32(u[40:]) +} + +func (u Utxo) OutputIndexBytes() []byte { + return u[40:44] +} + +func (u Utxo) Equal(x CacheOutput) bool { + return bytes.Equal(u[:], x[:]) +} + +func NewUtxo(hash [32]byte, value uint64, outIndex uint32) (u Utxo) { + copy(u[0:32], hash[:]) // txid + binary.BigEndian.PutUint64(u[32:40], value) + binary.BigEndian.PutUint32(u[40:], outIndex) + return +} + +// TxId is a bitcoin transaction id. The underlying slice is reversed, only +// when using the stringer does it apear in human readable format. +type TxId [32]byte + +func (t TxId) String() string { + var rev [32]byte + for k := range t { + rev[32-k-1] = t[k] + } + return hex.EncodeToString(rev[:]) +} + +func NewTxId(x [32]byte) (txId TxId) { + copy(txId[:], x[:]) + return +} + +func NewTxIdFromBytes(x []byte) (txId TxId, err error) { + if len(x) != 32 { + err = fmt.Errorf("invalid transaction hash length") + return + } + copy(txId[:], x[:]) + return +} + +// BlockHash is a bitcoin transaction id. The underlying slice is reversed, only +// when using the stringer does it apear in human readable format. +type BlockHash [32]byte + +func (bh BlockHash) String() string { + var rev [32]byte + for k := range bh { + rev[32-k-1] = bh[k] + } + return hex.EncodeToString(rev[:]) +} + +func NewBlockHash(x [32]byte) (blockHash BlockHash) { + copy(blockHash[:], x[:]) + return +} + +func NewBlockHashFromBytes(x []byte) (blockHash BlockHash, err error) { + if len(x) != 32 { + err = fmt.Errorf("invalid block hash length") + return + } + copy(blockHash[:], x[:]) + return +} + +// ScriptHash is a bitcoin transaction id. The underlying slice is reversed, only +// when using the stringer does it apear in human readable format. +type ScriptHash [32]byte + +func (bh ScriptHash) String() string { + return hex.EncodeToString(bh[:]) +} + +func NewScriptHash(x [32]byte) (scriptHash ScriptHash) { + copy(scriptHash[:], x[:]) + return +} + +func NewScriptHashFromBytes(x []byte) (scriptHash ScriptHash, err error) { + if len(x) != 32 { + err = fmt.Errorf("invalid script hash length") + return + } + copy(scriptHash[:], x[:]) + return +} + +// Spent Transaction: +// +// s + txin.PrevOutPoint.Hash + txin.PrevOutPoint.Index + blockhash = txid + txin_index + blockhash | [1 + 32 + 4 + 32] = [32 + 4] +// +// Transaction ID to Block mapping: +// +// t + txid + blockhash = nil | [1 + 32 + 32] = nil +type ( + TxKey [69]byte // Allocate max sized key, the prefix byte determines the lengths + TxValue [36]byte // allocate max sized value +) + +// NewTxSpent returns a TxKey and TxValue that maps a spent transaction to a +// location in a block. +func NewTxSpent(blockHash, txId, inPrevHash *chainhash.Hash, inPrevIndex, txInIndex uint32) (txKey TxKey, txValue TxValue) { + // Construct key + txKey[0] = 's' + copy(txKey[1:33], inPrevHash[:]) + binary.BigEndian.PutUint32(txKey[33:37], inPrevIndex) + copy(txKey[37:], blockHash[:]) + + // Construct value + copy(txValue[0:], txId[:]) + binary.BigEndian.PutUint32(txValue[32:36], txInIndex) + + return txKey, txValue +} + +// NewTxMapping returns a TxKey and TxValue that maps a tx id to a block hash. +func NewTxMapping(txId, blockHash *chainhash.Hash) (txKey TxKey) { + // Construct key + txKey[0] = 't' + copy(txKey[1:33], txId[:]) + copy(txKey[33:], blockHash[:]) + + return txKey +} diff --git a/database/tbcd/database_ext_test.go b/database/tbcd/database_ext_test.go new file mode 100644 index 000000000000..696b55e8e5a4 --- /dev/null +++ b/database/tbcd/database_ext_test.go @@ -0,0 +1,5 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbcd_test diff --git a/database/tbcd/level/level.go b/database/tbcd/level/level.go new file mode 100644 index 000000000000..b25fc531cfeb --- /dev/null +++ b/database/tbcd/level/level.go @@ -0,0 +1,875 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package level + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "sync" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/davecgh/go-spew/spew" + "github.com/juju/loggo" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/util" + + "github.com/hemilabs/heminetwork/database" + "github.com/hemilabs/heminetwork/database/level" + "github.com/hemilabs/heminetwork/database/tbcd" +) + +// Locking order: +// +// BlockHeaders +// BlocksMissing +// HeightHash +// Blocks +// +// Balances +// Utxos + +const ( + ldbVersion = 1 + + logLevel = "INFO" + verbose = false + + bhsLastKey = "last" + + minPeersRequired = 64 // minimum number of peers in good map before cache is purged +) + +type IteratorError error + +var log = loggo.GetLogger("level") + +var ErrIterator = IteratorError(errors.New("iteration error")) + +func init() { + loggo.ConfigureLoggers(logLevel) +} + +type ldb struct { + mtx sync.Mutex + blocksMissingCacheEnabled bool // XXX verify this code in tests + blocksMissingCache map[string]*cacheEntry // XXX purge and manages cache size + + // maybe remove this because it eats a bit of memory + peersGood map[string]struct{} + peersBad map[string]struct{} + + *level.Database + pool level.Pool +} + +var _ tbcd.Database = (*ldb)(nil) + +func New(ctx context.Context, home string) (*ldb, error) { + log.Tracef("New") + defer log.Tracef("New exit") + + ld, err := level.New(ctx, home, ldbVersion) + if err != nil { + return nil, err + } + log.Debugf("tbcdb database version: %v", ldbVersion) + l := &ldb{ + Database: ld, + pool: ld.DB(), + blocksMissingCacheEnabled: true, // XXX make setting + blocksMissingCache: make(map[string]*cacheEntry, 1024), + peersGood: make(map[string]struct{}, 1000), + peersBad: make(map[string]struct{}, 1000), + } + + return l, nil +} + +type ( + discardFunc func() + commitFunc func() error +) + +func (l *ldb) startTransaction(db string) (*leveldb.Transaction, commitFunc, discardFunc, error) { + bhsDB := l.pool[db] + tx, err := bhsDB.OpenTransaction() + if err != nil { + return nil, nil, nil, fmt.Errorf("%v open tansaction: %w", db, err) + } + d := true + discard := &d + df := func() { + if *discard { + log.Debugf("discarding transaction: %v", db) + tx.Discard() + } + } + cf := func() error { + err = tx.Commit() + if err != nil { + return fmt.Errorf("%v discard: %w", db, err) + } + *discard = false + return nil + } + + return tx, cf, df, nil +} + +func (l *ldb) MetadataGet(ctx context.Context, key []byte) ([]byte, error) { + log.Tracef("MetadataGet") + defer log.Tracef("MetadataGet exit") + + mdDB := l.pool[level.MetadataDB] + v, err := mdDB.Get(key, nil) + if err == leveldb.ErrNotFound { + return nil, database.NotFoundError(fmt.Sprintf("key not found: %v", + string(key))) + } + return v, err +} + +func (l *ldb) MetadataPut(ctx context.Context, key, value []byte) error { + log.Tracef("MetadataPut") + defer log.Tracef("MetadataPut exit") + + mdDB := l.pool[level.MetadataDB] + return mdDB.Put(key, value, nil) +} + +func (l *ldb) BlockHeaderByHash(ctx context.Context, hash []byte) (*tbcd.BlockHeader, error) { + log.Tracef("BlockHeaderByHash") + defer log.Tracef("BlockHeaderByHash exit") + + // It stands to reason that this code does not need a trasaction. The + // caller code will either receive or not receice an answer. It does + // not seem likely to be racing higher up in the stack. + + bhsDB := l.pool[level.BlockHeadersDB] + ebh, err := bhsDB.Get(hash, nil) + if err != nil { + if err == leveldb.ErrNotFound { + return nil, database.NotFoundError(fmt.Sprintf("block header not found: %x", hash)) + } + return nil, fmt.Errorf("block header get: %w", err) + } + return decodeBlockHeader(hash, ebh), nil +} + +func (l *ldb) BlockHeadersByHeight(ctx context.Context, height uint64) ([]tbcd.BlockHeader, error) { + log.Tracef("BlockHeadersByHeight") + defer log.Tracef("BlockHeadersByHeight exit") + + bhs := make([]tbcd.BlockHeader, 0, 4) + start := make([]byte, 8) + binary.BigEndian.PutUint64(start, height) + limit := make([]byte, 8) + binary.BigEndian.PutUint64(limit, height+2) + + hhDB := l.pool[level.HeightHashDB] + it := hhDB.NewIterator(&util.Range{Start: start, Limit: limit}, nil) + defer it.Release() + for it.Next() { + fh, hash := keyToHeightHash(it.Key()) + if fh != height { + // all done + break + } + bh, err := l.BlockHeaderByHash(ctx, hash) + if err != nil { + return nil, fmt.Errorf("headers by height: %v", err) + } + bhs = append(bhs, *bh) + } + if len(bhs) == 0 { + return nil, database.NotFoundError(fmt.Sprintf("not found")) + } + return bhs, nil +} + +func (l *ldb) BlockHeadersBest(ctx context.Context) ([]tbcd.BlockHeader, error) { + log.Tracef("BlockHeadersBest") + defer log.Tracef("BlockHeadersBest exit") + + // This function is a bit of a crapshoot. It will receive many calls + // and thus it is racing by definition. Avoid the lock and let the + // caller serialize the response. + + // XXX this code does not handle multiple "best" block headers. + + bhsDB := l.pool[level.BlockHeadersDB] + // Get last record + ebh, err := bhsDB.Get([]byte(bhsLastKey), nil) + if err != nil { + if err == leveldb.ErrNotFound { + return []tbcd.BlockHeader{}, nil + } + return nil, fmt.Errorf("block headers best: %w", err) + } + + // Convert height to hash, cheat because we know where height lives in ebh. + return l.BlockHeadersByHeight(ctx, binary.BigEndian.Uint64(ebh[0:8])) +} + +// heightHashToKey generates a sortable key from height and hash. With this key +// we can iterate over the block headers table and see what block records are +// missing. +func heightHashToKey(height uint64, hash []byte) []byte { + if len(hash) != chainhash.HashSize { + panic(fmt.Sprintf("invalid hash size: %v", len(hash))) + } + key := make([]byte, 8+1+chainhash.HashSize) + binary.BigEndian.PutUint64(key[0:8], height) + copy(key[9:], hash) + return key +} + +// keyToHeightHash reverses the process of heightHashToKey. +func keyToHeightHash(key []byte) (uint64, []byte) { + if len(key) != 8+1+chainhash.HashSize { + panic(fmt.Sprintf("invalid key size: %v", len(key))) + } + hash := make([]byte, chainhash.HashSize) // must make copy! + copy(hash, key[9:]) + return binary.BigEndian.Uint64(key[0:8]), hash +} + +// encodeBlockHeader encodes a database block header as [height,header] or +// [8+80] bytes. The hash is the leveldb table key. +func encodeBlockHeader(bh *tbcd.BlockHeader) (ebhr [88]byte) { + binary.BigEndian.PutUint64(ebhr[0:8], bh.Height) + copy(ebhr[8:], bh.Header[:]) + return +} + +// decodeBlockHeader reverse the process of encodeBlockHeader. The hash must be +// passed in but that is fine because it is the leveldb lookup key. +func decodeBlockHeader(hashSlice []byte, ebh []byte) *tbcd.BlockHeader { + // copy the values to prevent slicing reentrancy problems. + var ( + hash [32]byte + header [80]byte + ) + copy(hash[:], hashSlice) + copy(header[:], ebh[8:]) + return &tbcd.BlockHeader{ + Hash: hash[:], + Height: binary.BigEndian.Uint64(ebh[0:8]), + Header: header[:], + } +} + +func (l *ldb) BlockHeadersInsert(ctx context.Context, bhs []tbcd.BlockHeader) error { + log.Tracef("BlockHeadersInsert") + defer log.Tracef("BlockHeadersInsert exit") + + if len(bhs) == 0 { + return fmt.Errorf("block headers insert: no block headers to insert") + } + + // block headers + bhsTx, bhsCommit, bhsDiscard, err := l.startTransaction(level.BlockHeadersDB) + if err != nil { + return fmt.Errorf("block headers open transaction: %w", err) + } + defer bhsDiscard() + + // Make sure we are not inserting the same blocks + has, err := bhsTx.Has(bhs[0].Hash, nil) + if err != nil { + return fmt.Errorf("block headers insert has: %v", err) + } + if has { + return database.DuplicateError("block headers insert duplicate") + } + + // blocks missing + bmTx, bmCommit, bmDiscard, err := l.startTransaction(level.BlocksMissingDB) + if err != nil { + return fmt.Errorf("blocks missing open transaction: %w", err) + } + defer bmDiscard() + + // height hash + hhTx, hhCommit, hhDiscard, err := l.startTransaction(level.HeightHashDB) + if err != nil { + return fmt.Errorf("height hash open transaction: %w", err) + } + defer hhDiscard() + + // Insert missing blocks and block headers + var lastRecord []byte + hhBatch := new(leveldb.Batch) + bmBatch := new(leveldb.Batch) + bhsBatch := new(leveldb.Batch) + for k := range bhs { + hhKey := heightHashToKey(bhs[k].Height, bhs[k].Hash[:]) + // Height 0 is genesis, we do not want a missing block record for that. + if bhs[k].Height != 0 { + // Insert a synthesized height_hash key that serves as + // an index to see which blocks are missing. + bmBatch.Put(hhKey, []byte{}) + } + + // Store height_hash for future reference + hhBatch.Put(hhKey, []byte{}) + + // XXX reason about pre encoding. Due to the caller code being + // heavily reentrant the odds are not good that encoding would + // only happens once. The downside is that this encoding + // happens in the database transaction and is thus locked. + + // Encode block header as [hash][height,header] or [32][8+80] bytes + ebh := encodeBlockHeader(&bhs[k]) + bhsBatch.Put(bhs[k].Hash, ebh[:]) + lastRecord = ebh[:] + } + + // Insert last height into block headers XXX this does not deal with forks + bhsBatch.Put([]byte(bhsLastKey), lastRecord) + + // Write height hash batch + err = hhTx.Write(hhBatch, nil) + if err != nil { + return fmt.Errorf("height hash batch: %w", err) + } + + // Write missing blocks batch + err = bmTx.Write(bmBatch, nil) + if err != nil { + return fmt.Errorf("blocks missing batch: %w", err) + } + + // Write block headers batch + err = bhsTx.Write(bhsBatch, nil) + if err != nil { + return fmt.Errorf("block headers insert: %w", err) + } + + // height hash commit + err = hhCommit() + if err != nil { + return fmt.Errorf("height hash commit: %w", err) + } + + // blocks missing commit + err = bmCommit() + if err != nil { + return fmt.Errorf("blocks missing commit: %w", err) + } + + // block headers commit + err = bhsCommit() + if err != nil { + return fmt.Errorf("block headers commit: %w", err) + } + + return nil +} + +type cacheEntry struct { + height uint64 + timestamp time.Time +} + +// XXX return hash and height only +func (l *ldb) BlocksMissing(ctx context.Context, count int) ([]tbcd.BlockIdentifier, error) { + log.Tracef("BlocksMissing") + defer log.Tracef("BlocksMissing exit") + + // This is a read only call and it can be run without a transaction. + // False positives may be returned to the caller and it should mostly + // handle that. If a block is inserted multiple time it will be silently + // ignored. + + var blockCacheLen, x int + bmDB := l.pool[level.BlocksMissingDB] + bis := make([]tbcd.BlockIdentifier, 0, count) + it := bmDB.NewIterator(nil, nil) + defer it.Release() + for it.Next() { + bh := tbcd.BlockIdentifier{} + bh.Height, bh.Hash = keyToHeightHash(it.Key()) + bis = append(bis, bh) + + // cache the reply + if l.blocksMissingCacheEnabled { + l.mtx.Lock() + // XXX we MUST bind this map but for now let it be piggy + if _, ok := l.blocksMissingCache[string(bh.Hash)]; !ok { + l.blocksMissingCache[string(bh.Hash)] = &cacheEntry{ + height: bh.Height, + timestamp: time.Now(), + } + } + blockCacheLen = len(l.blocksMissingCache) + l.mtx.Unlock() + } + // if blockCacheLen >= 128 { + // log.Tracef("max cache %v", blockCacheLen) + // break + // } + + x++ + if x >= count { + break + } + } + + log.Debugf("BlocksMissing returning %v cached %v", len(bis), blockCacheLen) + + return bis, nil +} + +func (l *ldb) BlockInsert(ctx context.Context, b *tbcd.Block) (int64, error) { + log.Tracef("BlockInsert") + defer log.Tracef("BlockInsert exit") + + // Try cache first + var ce *cacheEntry + if l.blocksMissingCacheEnabled { + // XXX explain here why using string(b.Hash) is acceptable + l.mtx.Lock() + ce = l.blocksMissingCache[string(b.Hash)] + l.mtx.Unlock() + + defer func() { + // purge cache as well + l.mtx.Lock() + delete(l.blocksMissingCache, string(b.Hash)) + bmcl := len(l.blocksMissingCache) + l.mtx.Unlock() + // XXX string b.Hash is shit + log.Debugf("BlockInsert cached %v", bmcl) + }() + } + + // Determine block height either from cache or the database. + var bh *tbcd.BlockHeader + + // If cache entry is not found grab it from the database. + if ce == nil { + // Open the block headers database transaction + bhsDB := l.pool[level.BlockHeadersDB] + ebh, err := bhsDB.Get(b.Hash, nil) + if err != nil { + if err == leveldb.ErrNotFound { + return -1, database.NotFoundError(fmt.Sprintf( + "block insert block header not found: %v", + b.Hash)) + } + return -1, fmt.Errorf("block insert block header: %w", err) + } + // XXX only do the big endian decoding here!, less bcopy + bh = decodeBlockHeader(b.Hash, ebh) + } else { + bh = &tbcd.BlockHeader{ + Height: ce.height, + Hash: b.Hash, + } + } + + // Insert block without transaction, if it succeeds and the missing + // does not it will be simply redone. + bDB := l.pool[level.BlocksDB] + has, err := bDB.Has(b.Hash, nil) + if err != nil { + return -1, fmt.Errorf("block insert has: %v", err) + } + if !has { + // Insert block since we do not have it yet + err = bDB.Put(b.Hash, b.Block, nil) + if err != nil { + return -1, fmt.Errorf("blocks insert put: %v", err) + } + } + + // It's possible to remove the transaction for bm without a transaction + // as well since the only risk would be duplicate work. Reason about + // this some more. + + // Remove block identifier from blocks missing + key := heightHashToKey(bh.Height, bh.Hash) + bmDB := l.pool[level.BlocksMissingDB] + err = bmDB.Delete(key, nil) + if err != nil { + // Ignore not found + if err == leveldb.ErrNotFound { + log.Errorf("block insert delete from missing: %v", err) + } else { + return -1, fmt.Errorf("block insert delete from missing: %v", err) + } + } + // XXX think about Height type; why are we forced to mix types? + return int64(bh.Height), nil +} + +func (l *ldb) BlockByHash(ctx context.Context, hash []byte) (*tbcd.Block, error) { + log.Tracef("BlockByHash") + defer log.Tracef("BlockByHash exit") + + bDB := l.pool[level.BlocksDB] + eb, err := bDB.Get(hash, nil) + if err != nil { + if err == leveldb.ErrNotFound { + ch, _ := chainhash.NewHash(hash) + return nil, database.NotFoundError(fmt.Sprintf("block not found: %v", ch)) + } + return nil, fmt.Errorf("block get: %w", err) + } + return &tbcd.Block{ + Hash: hash, + Block: eb, + }, nil +} + +func (l *ldb) BlocksByTxId(ctx context.Context, txId tbcd.TxId) ([]tbcd.BlockHash, error) { + log.Tracef("BlocksByTxId") + defer log.Tracef("BlocksByTxId exit") + + blocks := make([]tbcd.BlockHash, 0, 2) + txDB := l.pool[level.TransactionsDB] + var txid [33]byte + txid[0] = 't' + copy(txid[1:], txId[:]) + it := txDB.NewIterator(util.BytesPrefix(txid[:]), nil) + defer it.Release() + for it.Next() { + block, err := tbcd.NewBlockHashFromBytes(it.Key()[33:]) + if err != nil { + return nil, err + } + blocks = append(blocks, block) + } + if err := it.Error(); err != nil { + return nil, fmt.Errorf("blocks by id iterator: %w", err) + } + if len(blocks) == 0 { + ch, _ := chainhash.NewHash(txId[:]) + return nil, database.NotFoundError(fmt.Sprintf("tx not found: %v", ch)) + } + + return blocks, nil +} + +func (l *ldb) SpendOutputsByTxId(ctx context.Context, txId tbcd.TxId) ([]tbcd.SpendInfo, error) { + log.Tracef("SpendOutputByOutpoint") + defer log.Tracef("SpendOutputByOutpoint exit") + + si := make([]tbcd.SpendInfo, 0, 2) + txDB := l.pool[level.TransactionsDB] + var key [1 + 32]byte + key[0] = 's' + copy(key[1:], txId[:]) + it := txDB.NewIterator(&util.Range{Start: key[:]}, nil) + defer it.Release() + for it.Next() { + if !bytes.Equal(it.Key()[1:33], key[1:33]) { + break + } + var s tbcd.SpendInfo + copy(s.TxId[:], it.Value()[0:32]) + copy(s.BlockHash[:], it.Key()[37:]) + s.InputIndex = binary.BigEndian.Uint32(it.Value()[32:36]) + si = append(si, s) + } + if err := it.Error(); err != nil { + return nil, fmt.Errorf("blocks by id iterator: %w", err) + } + if len(si) == 0 { + ch, _ := chainhash.NewHash(txId[:]) + return nil, database.NotFoundError(fmt.Sprintf("not found %v", ch)) + } + + return si, nil +} + +func (l *ldb) ScriptHashByOutpoint(ctx context.Context, op tbcd.Outpoint) (*tbcd.ScriptHash, error) { + log.Tracef("ScriptHashByOutpoint") + defer log.Tracef("ScriptHashByOutpoint exit") + + var uop [37]byte // 'u' tx_id idx + uop[0] = 'u' + copy(uop[1:], op[:]) + + uDB := l.pool[level.OutputsDB] + scriptHash, err := uDB.Get(uop[:], nil) + if err != nil { + return nil, fmt.Errorf("script hash by outpoint: %w", err) + } + + sh, err := tbcd.NewScriptHashFromBytes(scriptHash) + return &sh, err +} + +func (l *ldb) BalanceByScriptHash(ctx context.Context, sh tbcd.ScriptHash) (uint64, error) { + log.Tracef("BalanceByScriptHash") + defer log.Tracef("BalanceByScriptHash exit") + + var ( + start [33]byte + balance uint64 + ) + start[0] = 'h' + copy(start[1:], sh[:]) + oDB := l.pool[level.OutputsDB] + it := oDB.NewIterator(util.BytesPrefix(start[:]), nil) + defer it.Release() + for it.Next() { + balance += binary.BigEndian.Uint64(it.Value()) + } + if err := it.Error(); err != nil { + return 0, IteratorError(err) + } + + return balance, nil +} + +func (l *ldb) UtxosByScriptHash(ctx context.Context, sh tbcd.ScriptHash, start uint64, count uint64) ([]tbcd.Utxo, error) { + log.Tracef("UtxosByScriptHash") + defer log.Tracef("UtxosByScriptHash exit") + + var prefix [33]byte + utxos := make([]tbcd.Utxo, 0, 32) + prefix[0] = 'h' + copy(prefix[1:], sh[:]) + oDB := l.pool[level.OutputsDB] + it := oDB.NewIterator(util.BytesPrefix(prefix[:]), nil) + defer it.Release() + skip := start + for it.Next() { + if skip > 0 { + skip-- + continue + } + index := binary.BigEndian.Uint32(it.Key()[65:]) + value := binary.BigEndian.Uint64(it.Value()) + var txId tbcd.TxId + copy(txId[:], it.Key()[33:65]) + utxos = append(utxos, tbcd.NewUtxo(txId, value, index)) + + if len(utxos) >= int(count) { + break + } + } + if err := it.Error(); err != nil { + return nil, IteratorError(err) + } + + return utxos, nil +} + +func (l *ldb) BlockUtxoUpdate(ctx context.Context, utxos map[tbcd.Outpoint]tbcd.CacheOutput) error { + log.Tracef("BlockUtxoUpdate") + defer log.Tracef("BlockUtxoUpdate exit") + + // outputs + outsTx, outsCommit, outsDiscard, err := l.startTransaction(level.OutputsDB) + if err != nil { + return fmt.Errorf("outputs open db transaction: %w", err) + } + defer outsDiscard() + + outsBatch := new(leveldb.Batch) + for op, utxo := range utxos { + // op is already 'u' tx_id idx + + var hop [69]byte // 'h' script_hash tx_id tx_output_idx + hop[0] = 'h' + copy(hop[1:33], utxo.ScriptHashSlice()) + copy(hop[33:65], op.TxId()) + copy(hop[65:], utxo.OutputIndexBytes()) + + if utxo.IsDelete() { + // Delete balance and utxos + outsBatch.Delete(op[:][:]) + outsBatch.Delete(hop[:]) + } else { + // Add utxo to balance and utxos + outsBatch.Put(op[:], utxo.ScriptHashSlice()) + outsBatch.Put(hop[:], utxo.ValueBytes()) + } + // XXX this probably should be done by the caller but we do it + // here to lower memory pressure as large gobs of data are + // written to disk. + delete(utxos, op) + } + + // Write outputs batch + err = outsTx.Write(outsBatch, nil) + if err != nil { + return fmt.Errorf("outputs insert: %w", err) + } + + // outputs commit + err = outsCommit() + if err != nil { + return fmt.Errorf("outputs commit: %w", err) + } + + return nil +} + +func (l *ldb) BlockTxUpdate(ctx context.Context, txs map[tbcd.TxKey]*tbcd.TxValue) error { + log.Tracef("BlockTxUpdate") + defer log.Tracef("BlockTxUpdate exit") + + // transactions + txsTx, txsCommit, txsDiscard, err := l.startTransaction(level.TransactionsDB) + if err != nil { + return fmt.Errorf("transactions open db transaction: %w", err) + } + defer txsDiscard() + + txsBatch := new(leveldb.Batch) + for k, v := range txs { + // cache is being emptied so we can slice it here. + var key, value []byte + switch k[0] { + case 't': + key = k[0:65] + value = nil + + case 's': + key = k[:] + value = v[:] + default: + return fmt.Errorf("invalid cache entry: %v", spew.Sdump(k)) + } + + txsBatch.Put(key, value) + // log.Infof("%v:%v", spew.Sdump(key), spew.Sdump(value)) + // // XXX this probably should be done by the caller but we do it + // // here to lower memory pressure as large gobs of data are + // // written to disk. + delete(txs, k) + } + + // Write transactions batch + err = txsTx.Write(txsBatch, nil) + if err != nil { + return fmt.Errorf("transactions insert: %w", err) + } + + // transactions commit + err = txsCommit() + if err != nil { + return fmt.Errorf("transactions commit: %w", err) + } + + return nil +} + +func (l *ldb) PeersStats(ctx context.Context) (int, int) { + log.Tracef("PeersInsert") + defer log.Tracef("PeersInsert exit") + + l.mtx.Lock() + defer l.mtx.Unlock() + return len(l.peersGood), len(l.peersBad) +} + +func (l *ldb) PeersInsert(ctx context.Context, peers []tbcd.Peer) error { + log.Tracef("PeersInsert") + defer log.Tracef("PeersInsert exit") + + l.mtx.Lock() + for k := range peers { + p := peers[k] + a := net.JoinHostPort(p.Host, p.Port) + if len(a) < 7 { + // 0.0.0.0 + continue + } + if _, ok := l.peersBad[a]; ok { + // Skip bad peers + continue + } + if _, ok := l.peersGood[a]; ok { + // Not strictly needed to skip but this os working pseudode code + continue + } + + l.peersGood[a] = struct{}{} + } + allGoodPeers := len(l.peersGood) + allBadPeers := len(l.peersBad) + l.mtx.Unlock() + + log.Debugf("PeersInsert exit %v good %v bad %v", + len(peers), allGoodPeers, allBadPeers) + + return nil +} + +func (l *ldb) PeerDelete(ctx context.Context, host, port string) error { + log.Tracef("PeerDelete") + defer log.Tracef("PeerDelete exit") + + a := net.JoinHostPort(host, port) + if len(a) < 7 { + // 0.0.0.0 + return nil + } + + l.mtx.Lock() + if _, ok := l.peersGood[a]; ok { + delete(l.peersGood, a) + l.peersBad[a] = struct{}{} + } + + // Crude hammer to reset good/bad state of peers + if len(l.peersGood) < minPeersRequired { + // Kill all peers to force caller to reseed. This happens when + // network is down for a while and all peers are moved into + // bad map. + l.peersGood = make(map[string]struct{}, 1000) + l.peersBad = make(map[string]struct{}, 1000) + log.Tracef("peer cache purged") + } + + allGoodPeers := len(l.peersGood) + allBadPeers := len(l.peersBad) + + l.mtx.Unlock() + + log.Debugf("PeerDelete exit good %v bad %v", allGoodPeers, allBadPeers) + + return nil +} + +func (l *ldb) PeersRandom(ctx context.Context, count int) ([]tbcd.Peer, error) { + log.Tracef("PeersRandom") + + x := 0 + peers := make([]tbcd.Peer, 0, count) + + l.mtx.Lock() + allGoodPeers := len(l.peersGood) + allBadPeers := len(l.peersBad) + for k := range l.peersGood { + h, p, err := net.SplitHostPort(k) + if err != nil { + continue + } + peers = append(peers, tbcd.Peer{Host: h, Port: p}) + x++ + if x >= count { + break + } + } + l.mtx.Unlock() + + log.Debugf("PeersRandom exit %v (good %v bad %v)", len(peers), + allGoodPeers, allBadPeers) + + // XXX For now return peers in order and let the stack above deal with it. + return peers, nil +} diff --git a/database/tbcd/level/level_test.go b/database/tbcd/level/level_test.go new file mode 100644 index 000000000000..2058ed75a244 --- /dev/null +++ b/database/tbcd/level/level_test.go @@ -0,0 +1,419 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package level + +import ( + "bytes" + "context" + "crypto/rand" + "encoding/binary" + "fmt" + "io" + "os" + "reflect" + "sort" + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" + "github.com/juju/loggo" + + "github.com/hemilabs/heminetwork/database" + "github.com/hemilabs/heminetwork/database/tbcd" +) + +func bytes2Block(block []byte) (*wire.MsgBlock, error) { + var b wire.MsgBlock + err := b.Deserialize(bytes.NewReader(block)) + if err != nil { + return nil, fmt.Errorf("Deserialize: %v", err) + } + return &b, nil +} + +func bytes2Header(header []byte) (*wire.BlockHeader, error) { + var bh wire.BlockHeader + err := bh.Deserialize(bytes.NewReader(header)) + if err != nil { + return nil, fmt.Errorf("Deserialize: %v", err) + } + return &bh, nil +} + +func h2b(wbh *wire.BlockHeader) []byte { + hb, err := header2Bytes(wbh) + if err != nil { + panic(err) + } + return hb +} + +func header2Bytes(wbh *wire.BlockHeader) ([]byte, error) { + var b bytes.Buffer + err := wbh.Serialize(&b) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +// random returns a variable number of random bytes. +func random(n int) []byte { + buffer := make([]byte, n) + _, err := io.ReadFull(rand.Reader, buffer) + if err != nil { + panic(err) + } + return buffer +} + +func TestEncodeDecodeBlockHeader(t *testing.T) { + cp := chaincfg.TestNet3Params + genesisBH := cp.GenesisBlock.Header + genesisHash := cp.GenesisHash + + bh := tbcd.BlockHeader{ + Hash: genesisHash[:], + Height: 0x1122334455667788, // we need not zero to test decoding of height + Header: h2b(&genesisBH), + } + t.Logf("%v", spew.Sdump(bh)) + er := encodeBlockHeader(&bh) + dr := decodeBlockHeader(bh.Hash, er[:]) + if !reflect.DeepEqual(bh, *dr) { + t.Fatalf("encode decode block header wanted %v got %v", + spew.Sdump(bh), spew.Sdump(*dr)) + } +} + +func TestKey(t *testing.T) { + height := uint64(0xffeeddcc11223344) + hv := []byte{1, 3, 3, 7} + hash := chainhash.DoubleHashH(hv) + key := heightHashToKey(height, hash[:]) + + heightO, hashO := keyToHeightHash(key) + if height != heightO { + t.Fatalf("invalid height wanted %v got %v", height, heightO) + } + if !bytes.Equal(hash[:], hashO) { + t.Fatalf("invalid hash wanted %v got %v", + spew.Sdump(hash), spew.Sdump(hashO)) + } + + t.Logf("height %x", height) + t.Logf("key %v", spew.Sdump(key)) + t.Logf("%v%v", spew.Sdump(hash[:]), spew.Sdump(hashO)) +} + +type ByteSlice [][]byte + +func (x ByteSlice) Len() int { return len(x) } +func (x ByteSlice) Less(i, j int) bool { return bytes.Compare(x[i], x[j]) == -1 } +func (x ByteSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func TestKeyOrder(t *testing.T) { + // Create slice in reverse order + count := uint64(10) + keys := make(ByteSlice, count) + for i := uint64(0); i < count; i++ { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, i) + hash := chainhash.DoubleHashH(b) + keys[count-1-i] = heightHashToKey(i, hash[:]) + } + log.Infof("%v", spew.Sdump(keys)) + + // Now sort + sort.Sort(keys) + log.Infof("%v", spew.Sdump(keys)) + + for i := uint64(0); i < count; i++ { + height, hash := keyToHeightHash(keys[i]) + if i != height { + t.Fatalf("invalid height wanted %v got %v", i, height) + } + + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, i) + expectedHash := chainhash.DoubleHashH(b) + if !bytes.Equal(expectedHash[:], hash) { + t.Fatalf("invalid hash wanted %x got %x", expectedHash, hash) + } + } +} + +func TestLevelDB(t *testing.T) { + // Missing blocks + // 1 000 000 000 + + loggo.ConfigureLoggers("INFO") + + dir, err := os.MkdirTemp("", "leveldbtest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + ctx := context.Background() + ldb, err := New(ctx, dir) + if err != nil { + t.Fatal(err) + } + defer func() { + err := ldb.Close() + if err != nil { + t.Fatalf("close: %v", err) + } + }() + + // Create fake blockchain somewhat resembling tbc calls + + // Insert genesis + cp := &chaincfg.TestNet3Params + gbh, err := header2Bytes(&cp.GenesisBlock.Header) + if err != nil { + t.Fatal(err) + } + + // Insert genesis + tgbh := tbcd.BlockHeader{ + Height: 0, + Hash: cp.GenesisHash[:], + Header: gbh, + } + err = ldb.BlockHeadersInsert(ctx, []tbcd.BlockHeader{tgbh}) + if err != nil { + t.Fatalf("block headers insert: %v", err) + } + + missing, err := ldb.BlocksMissing(ctx, 16) + if err != nil { + t.Fatalf("block headers missing: %v", err) + } + + if len(missing) != 0 { + t.Fatal("genesis should not be returned") + } + + // Insert fake block headers + count := uint64(64) + bhs := make([]tbcd.BlockHeader, 0, count+1) + bhs = append(bhs, tgbh) // need genesis for prevhash + for i := uint64(1); i < count; i++ { + bits := uint32(i + 4567) + nonce := uint32(i + 1337) + prevHash, err := chainhash.NewHash(bhs[i-1].Hash[:]) + if err != nil { + t.Fatalf("prevhash %v", err) + } + merkleHash := chainhash.DoubleHashH(prevHash[:]) + wbh := wire.NewBlockHeader(1, prevHash, &merkleHash, bits, nonce) + blockHash := wbh.BlockHash() + t.Logf("height %v prev %v", i, prevHash) + bhs = append(bhs, tbcd.BlockHeader{ + Height: i, + Hash: database.ByteArray(blockHash[:]), + Header: h2b(wbh), + }) + } + t.Logf("%v", spew.Sdump(bhs)) + // Insert missing blocks + err = ldb.BlockHeadersInsert(ctx, bhs[1:]) // skip genesis insert + if err != nil { + t.Fatalf("block headers insert: %v", err) + } + + expectedMissingBH := 16 + missing, err = ldb.BlocksMissing(ctx, expectedMissingBH) + if err != nil { + t.Fatalf("block headers missing: %v", err) + } + t.Logf("%v", spew.Sdump(missing)) + + if len(missing) != min(expectedMissingBH, int(count-1)) { + t.Fatalf("%v %v %v", len(missing), expectedMissingBH, count) + } + + // Start at height 1 + height := uint64(1) + for k := range missing { + if height != bhs[height].Height { + t.Fatalf("unexpected internal height wanted %v got %v", + height, bhs[height].Height) + } + if bhs[height].Height != missing[k].Height { + t.Fatalf("unexpected missing height wanted %v got %v", + bhs[height].Height, missing[k].Height) + } + if !bytes.Equal(bhs[height].Hash, missing[k].Hash) { + t.Fatalf("unexpected missing hash wanted %v got %v", + bhs[height].Hash, missing[k].Hash) + } + + height++ + } + + // Insert missing blocks + for i := uint64(1); i < count; i++ { + b := tbcd.Block{ + Hash: bhs[i].Hash, + Block: []byte{'i', 'a', 'm', 'b', 'l', 'o', 'c', 'k'}, + } + insertedHeight, err := ldb.BlockInsert(ctx, &b) + if err != nil { + t.Fatal(err) + } + log.Infof("inserted height: %v", insertedHeight) + } + + // Ensure blocks missing table is updated + missing, err = ldb.BlocksMissing(ctx, expectedMissingBH) + if err != nil { + t.Fatalf("block headers missing: %v", err) + } + if len(missing) != 0 { + t.Fatalf("expected missing table to be empty: %v", spew.Sdump(missing)) + } + if len(ldb.blocksMissingCache) != 0 { + t.Fatalf("expected missing blocks cache to be empty: %v", + spew.Sdump(ldb.blocksMissingCache)) + } +} + +//func TestBitcoinBits(t *testing.T) { +// // Decode block +// block381 := `01000000c5b9489065fa7e1ac4facc51a5a0ccc2111911609f43386ebe7ca1d200000000a0db3bbb22a2a8441d84dbe335c24959ea3d3d6e91bf67e66bbcb0d7e0a9c4836a834a4dffff001d041813660201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e046a834a4d017e062f503253482fffffffff0100f2052a01000000232103dac3fb8de40965f42fb4afb3baa07d3304bc2aa28cfc25f12b52f1523681451dac00000000010000001518b50db063333a3261b9b41e887b4aa5b69becdc9967550507c120e22a764967000000004a493046022100e49de3c89180769db346145cdda48323ddecc2af0041293432528767b18407650221009f7878deb054e4f9c0e6aecbe6de15f5d829041c11f7952d33e96c76ada1258b01ffffffff322948a4806acfeca2b32248d0e183c8eb09d5e5ef48adf33777307635414cc0000000004a493046022100ba88d34e4d4fd85ab5e4d77cb74f71c87a24235bcbe39cf4334633f70ff27233022100b5aa1b96bab59457d3d837473de1e4f9f89ba3ee39964463952271c5b4140fa001ffffffffcf330295467623ec1378dc6fa312103ad8a210b3e1351f2f4b6a57ac43fcd472000000004a493046022100b21560dfda52352c4416c1e48496659ea3d29e4e25706a991986864210bc759e0221009c1e45af6e2eba0883a862442d85a2b48c3395e35a4276f535cd70d45a971c7401ffffffffeeed0f4d975db8f66788f809ecf8c351d19ff5805276ef31983bc5682548342d0000000049483045022100e02cc0b4bf8a126807b1577819944c1bb13e8f4028cf7df0a0729013d511b071022010a1bcdefca334588939f9fe40e0d8607588191684fce0f46180a139305b8b4001ffffffffc8ac0a2fb1c01e0e0a5339d296eb072b2b9f9cb1d410a1fdd69a2c797094dda50000000049483045022016ba8f50d7f30be7e4a68c3d50368d577e2ef6c8b60842725ae636b2985776fc022100bb39d47d1955ffca47920d743bcd6f05b31ea2bf3dc7ede225eb4c901126b48901fffffffff1b03cf0680b9ef33fd311f6bbc6db3f1c164f9341f48a02df1905cec4ce241b000000004948304502201dbbfabc47f6da84ceedbc92b792d4a8ef632f0bddf7ebfad5ca21f3731f450502210098751ccf37fd97ff82446486d4c1d62860c2080a1128ea5ddb0d30bfde3cd7a801ffffffff1fe6898ac074a680fe7458ff87a03956db73a880d2ace6539efcc43002bd97ed000000004a493046022100f8a83fadb06af9c0cc730f17ae47fe7a09cada9eae623b8dd86bf365ef0e20480221009a10b073b2a8b313d975f801213efdf12b94141d7b6a8e98de3b0c67ee1cef4c01ffffffff6fd85c0213cfe9863573596a4d5f1509ac41a91b572e6c1bdafe46d9249a5fa4000000004a493046022100f3e98f3e76cc0f533b0e1cccd82650b704e31e3e7e62bf81bb474cf2add58ebf022100f77003eec814a3336cc305b8461cf3ccb19b1f18f06f66208ed31c3e468466ed01ffffffff9e93a056a6515e7916fc049578708d188c2146d3c12638acac92e0b72e076edd000000004a4930460221008ee8d7348aed82a8d074753ab4c8dbdd28a668da821269c4cd0c5c253738cab7022100b06a0208d60af1be6303dd883fd05f964a42f7de317761641ec1158944f52b6b01ffffffff0ecc7b73d8cd5d377d74d836bb6e3473478554a923154286ddaf6985948fd9d300000000494830450221008159ed783bc717ff5a6502cd87a8d8144fae74c6fc6943a5a38da7170203cb3802207e31577a576bc01510cb2280f918a371f63eee44cd2b4490c0994d261787916e01ffffffff78966e9f0a2d4452ab2418249fa6fb1a325a04f039d015899141a82aa5a6c05c000000004847304402206655b13198e413ac8f1aa8926d4617560758cf8b5045afdfc9116da0873ed89802205db55cf3f398467bfc6997f68c881e5f2a7225293ebbd2af40d15df6de4ef87701ffffffff69f2096bbede7015fee2fb307f7d7dd084641b7f4af5c3074dc7b2b6df03277c000000004a493046022100c9199296673a1beae598a6d2348ef13ad1b9f15eebaa825d2282adf017cbb5f0022100b54934e40ff0194a53dcaa9d017c36a93dbb53aa45fe21ab93b07fbb58570d5501ffffffff3c11b146d43fd62ec36b733942a52ba0c352c95a3f078808a38d080898cb83300000000048473044022004c64773b9e6a17cfca7ff583be650104c0538940289b2da8f8bebbd32e486b302200174d8f0938a0f9eeab4c4b137581e032f06d4740e3b0ad9d0423a0a8de65af101ffffffff59ac3c37adfa89b9a907ef9d485c57262e9283e1eb96069c2de04369ef1b3c7600000000494830450220306f3ac72de9dbeb1ec139e4e89cc3b3b9bcb63747bf0e165fcfc773f3669832022100c00a16800f16bf1c71ac6c2989b42d974b0ec2f3e3671325fb2cae52a1c569d801ffffffffb4bbecee818dd986e5ab82f36dbd5ccc29ab134614e304c0a397e14082fe7bb7000000004a493046022100ed68e0303052b41ffd80c1e905cee5547e92422d43b73e473a615e4a47146bb5022100ecab3f92c62477350753b4efea19d608fcce15b1b2c38fbe905e9d1f9ad7631f01ffffffff7546bbac9ae1c8980da6e8c154b368eb4df305b6f3f27ff38f195a13c9ee0484000000004948304502202288566af2b68b6982d1244e293ea3d7c156a425329b7f61b272e4deec317bea022100d9739976b442d35c32830cb2c105e0d7275f7efaa99eaeea4b24a553267a31fc01ffffffffd15854d1e5ba349daf72089f470b24557a2be25105b7831a3f18a62fb8bab677000000004948304502206e3a23075e0248ea8cabc7c875b4cfd9f036c1c4f358a00ec152fc96d1cb6cf8022100d34c018815f63c65f5364061369382b31d579cd6d8a4afe9ec1f03ba66d7717801ffffffffdf686a7f31c2c1de6a608553b26d6336434719fa45428eb3df59bbef75ce9e7e000000004948304502200a22a24a8f817a2f24d3f8c2670f3cb25cd389ce25e0d45eeb0aea08563c5c9802210081ff14edb230a44e5b52e35f573676096a937fc27cc830b153b229b92cac75c101ffffffffd226fea91b99c5a31a034d340f647b722e50950c96a876eb96569efaeaf3b227000000004a4930460221009684e60a7fd61362d0dad79858044aa4a7b878b3f0bd432e384fe4c7e6c90bde0221009883e4f739cffe574bac5bed0a4e69708433973a2490d9415d303614fc31be4701fffffffff640c60ea438dc020048599869836f5323ef47477ee17caddf076ed428898f7100000000494830450220028eb7617dc161a282512c81975d41a1594c05f34cb26fb759682bf784da7071022100a0913abea7229b3c465a4fa32dc861f72ef684e8dd3f19aac5f0f74ea39c03cf01ffffffffd59d2a49b1883c6f7ac68a9d2649dc0dde3f0205e19d8fdaf8065381f9ba61cc000000004a4930460221009f5b27dfd397423a04cab52ee6e8215e290e9666309f0f59f5bc5f6c207d3639022100f5a79133db2cc786140aeee0bf7c8a81adca6071928e8210f1c9f0c653e2f04201ffffffff0240195e29010000001976a914944a7d4b3a8d3a5ecf19dfdfd8dcc18c6f1487dd88acc0c01e49170000001976a91432040178c5cf81cb200ab99af1131f187745b51588ac00000000` +// +// bb, err := hex.DecodeString(block381) +// if err != nil { +// t.Fatal(err) +// } +// // decode +// b, err := btcutil.NewBlockFromBytes(bb) +// if err != nil { +// t.Fatal(err) +// } +// txs := b.Transactions() +// chainParams := &chaincfg.TestNet3Params +// for k := range txs { +// tx := txs[k] +// t.Logf("tx %v %v", tx.Index(), tx.Hash()) +// if blockchain.IsCoinBase(tx) { +// t.Logf("coinbase! %v", spew.Sdump(tx.MsgTx())) +// } +// for kk := range tx.MsgTx().TxOut { +// scriptClass, _, _, err := txscript.ExtractPkScriptAddrs( +// tx.MsgTx().TxOut[kk].PkScript, &chaincfg.TestNet3Params, +// ) +// t.Logf("---- %v", spew.Sdump(scriptClass)) +// +// p, err := txscript.ParsePkScript(tx.MsgTx().TxOut[kk].PkScript) +// if err != nil { +// t.Logf("ERROR: %v %v", kk, err) +// continue +// } else { +// t.Logf("tx %v", spew.Sdump(p)) +// } +// a, err := p.Address(chainParams) +// if err != nil { +// t.Logf("ERROR address: %v %v", kk, err) +// } else { +// t.Logf("tx address %v", spew.Sdump(a)) +// } +// } +// } +//} +// +//func TestDumpIndex(t *testing.T) { +// levelDBHome := "~/.tbcd" +// network := "testnet3" +// +// ctx, cancel := context.WithCancel(context.Background()) +// defer cancel() +// +// // Open existing DB +// db, err := New(ctx, filepath.Join(levelDBHome, network)) +// if err != nil { +// t.Fatal(err) +// } +// defer func() { +// err := db.Close() +// if err != nil { +// t.Fatalf("close: %v", err) +// } +// }() +// +// outsDB := db.pool[level.OutputsDB] +// it := outsDB.NewIterator(nil, nil) +// defer it.Release() +// for it.Next() { +// t.Logf("outputs key %vvalue %v", spew.Sdump(it.Key()), spew.Sdump(it.Value())) +// } +// +// bsDB := db.pool[level.BalancesDB] +// bsIt := bsDB.NewIterator(&util.Range{Start: nil, Limit: nil}, nil) +// defer bsIt.Release() +// for bsIt.Next() { +// t.Logf("balances key %vvalue %v", spew.Sdump(bsIt.Key()), spew.Sdump(bsIt.Value())) +// } +//} +// +//func TestIndex(t *testing.T) { +// // t.Skip() +// +// // start block +// levelDBHome := "~/.tbcd" +// network := "testnet3" +// +// ctx, cancel := context.WithCancel(context.Background()) +// defer cancel() +// +// // Open existing DB +// db, err := New(ctx, filepath.Join(levelDBHome, network)) +// if err != nil { +// t.Fatal(err) +// } +// defer func() { +// err := db.Close() +// if err != nil { +// t.Fatalf("close: %v", err) +// } +// }() +// +// startHeight := uint64(0) +// count := uint64(10) // block 381 is the first to spend transactions +// start := time.Now() +// log.Infof("Starting to index to height %v at %v", startHeight, start) +// elapsed := time.Now() +// for height := startHeight; height < startHeight+count; height++ { +// bhs, err := db.BlockHeadersByHeight(ctx, height) +// if err != nil { +// t.Fatalf("block headers by height %v: %v", height, err) +// } +// t.Logf("%v", bhs) +// _ = elapsed +// //b, err := db.BlockByHash(ctx, bhs[0].Hash) +// //if err != nil { +// // t.Fatalf("block by hash %v: %v", height, err) +// //} +// //bh, btxs, err := tbcd.BlockTxs(&chaincfg.TestNet3Params, b.Block) +// //if err != nil { +// // t.Fatalf("block transactions %v: %v", height, err) +// //} +// //err = db.BlockTxUpdate(ctx, bh[:], btxs) +// //if err != nil { +// // // t.Fatalf("%v", spew.Sdump(btxs)) +// // t.Fatalf("block utxos %v: %v", height, err) +// //} +// //if height%1000 == 0 { +// // log.Infof("height %v %v", height, time.Now().Sub(elapsed)) +// // elapsed = time.Now() +// //} +// } +// log.Infof("Ending index height %v took %v", count, time.Now().Sub(start)) +//} diff --git a/docker/bfgd/Dockerfile b/docker/bfgd/Dockerfile index 75b8c21a791b..475a9ec81e75 100644 --- a/docker/bfgd/Dockerfile +++ b/docker/bfgd/Dockerfile @@ -1,5 +1,9 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + # Build stage -FROM golang:1.22.0-alpine@sha256:8e96e6cff6a388c2f70f5f662b64120941fcd7d4b89d62fec87520323a316bd9 as builder +FROM golang:1.22.1-alpine@sha256:fc5e5848529786cf1136563452b33d713d5c60b2c787f6b2a077fa6eeefd9114 as builder # Add ca-certificates, timezone data, make and git RUN apk --no-cache add --update ca-certificates tzdata make git diff --git a/docker/bssd/Dockerfile b/docker/bssd/Dockerfile index a16e322fc080..20b60e6aeea5 100644 --- a/docker/bssd/Dockerfile +++ b/docker/bssd/Dockerfile @@ -1,5 +1,9 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + # Build stage -FROM golang:1.22.0-alpine@sha256:8e96e6cff6a388c2f70f5f662b64120941fcd7d4b89d62fec87520323a316bd9 as builder +FROM golang:1.22.1-alpine@sha256:fc5e5848529786cf1136563452b33d713d5c60b2c787f6b2a077fa6eeefd9114 as builder # Add ca-certificates, timezone data, make and git RUN apk --no-cache add --update ca-certificates tzdata make git diff --git a/docker/popmd/Dockerfile b/docker/popmd/Dockerfile index 08c5707f7e0c..5a1e2f58ec61 100644 --- a/docker/popmd/Dockerfile +++ b/docker/popmd/Dockerfile @@ -1,5 +1,9 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + # Build stage -FROM golang:1.22.0-alpine@sha256:8e96e6cff6a388c2f70f5f662b64120941fcd7d4b89d62fec87520323a316bd9 as builder +FROM golang:1.22.1-alpine@sha256:fc5e5848529786cf1136563452b33d713d5c60b2c787f6b2a077fa6eeefd9114 as builder # Add ca-certificates, timezone data, make and git RUN apk --no-cache add --update ca-certificates tzdata make git diff --git a/e2e/.env b/e2e/.env new file mode 100644 index 000000000000..2164db7b0b6d --- /dev/null +++ b/e2e/.env @@ -0,0 +1,7 @@ +ADMIN_PRIVATE_KEY=dfe61681b31b12b04f239bc0692965c61ffc79244ed9736ffa1a72d00a23a530 +L2OO_ADDRESS=0xD3292428DE99a781A4A5e503622E8c80E5383e20 +POPM_BTC_PRIVATE_KEY=72a2c41c84147325ce3c0f37697ef1e670c7169063dda89be9995c3c5219740f +BTC_ADDRESS=mw47rj9rG25J67G6W8bbjRayRQjWN5ZSEG +# unused pks +# 7842c4d618821f836ee741ed7a0977b0a57a0714b71b4adbd94b14eb4e469398 +# 2d872df4fe08a18357921c7640a2eceb532f47d8979b2936d36262ad47141855 \ No newline at end of file diff --git a/e2e/deploy-config.json b/e2e/deploy-config.json new file mode 100644 index 000000000000..410b68db3d7f --- /dev/null +++ b/e2e/deploy-config.json @@ -0,0 +1,58 @@ +{ + "l1ChainID": 1337, + "l2ChainID": 901, + "l2BlockTime": 1, + "maxSequencerDrift": 300, + "sequencerWindowSize": 200, + "channelTimeout": 120, + "p2pSequencerAddress": "0x78697c88847dfbbb40523e42c1f2e28a13a170be", + "batchInboxAddress": "0xff00000000000000000000000000000000000901", + "batchSenderAddress": "0x78697c88847dfbbb40523e42c1f2e28a13a170be", + "cliqueSignerAddress": "0x78697c88847dfbbb40523e42c1f2e28a13a170be", + "l1UseClique": true, + "l1StartingBlockTag": "0x0", + "l2OutputOracleSubmissionInterval": 10, + "l2OutputOracleStartingTimestamp": 0, + "l2OutputOracleStartingBlockNumber": 0, + "l2OutputOracleProposer": "0x78697c88847dfbbb40523e42c1f2e28a13a170be", + "l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + "l2GenesisBlockGasLimit": "0x1c9c380", + "l1BlockTime": 3, + "baseFeeVaultRecipient": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", + "l1FeeVaultRecipient": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", + "sequencerFeeVaultRecipient": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "baseFeeVaultWithdrawalNetwork": "remote", + "l1FeeVaultWithdrawalNetwork": "remote", + "sequencerFeeVaultWithdrawalNetwork": "remote", + "proxyAdminOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "finalSystemOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "superchainConfigGuardian": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "finalizationPeriodSeconds": 2, + "fundDevAccounts": true, + "l2GenesisBlockBaseFeePerGas": "0x1", + "gasPriceOracleOverhead": 2100, + "gasPriceOracleScalar": 1000000, + "enableGovernance": true, + "governanceTokenSymbol": "OP", + "governanceTokenName": "Optimism", + "governanceTokenOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "eip1559Denominator": 50, + "eip1559DenominatorCanyon": 250, + "eip1559Elasticity": 6, + "l1GenesisBlockTimestamp": "0x0", + "l2GenesisRegolithTimeOffset": "0x0", + "l2GenesisDeltaTimeOffset": null, + "l2GenesisCanyonTimeOffset": "0x0", + "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", + "faultGameMaxDepth": 44, + "faultGameMaxDuration": 1200, + "outputBisectionGameGenesisBlock": 0, + "outputBisectionGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "outputBisectionGameSplitDepth": 14, + "systemConfigStartBlock": 0, + "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000" +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/.chainId b/e2e/deployments/devnetL1/.chainId new file mode 100644 index 000000000000..fa1bddfd0214 --- /dev/null +++ b/e2e/deployments/devnetL1/.chainId @@ -0,0 +1 @@ +1337 \ No newline at end of file diff --git a/e2e/deployments/devnetL1/AddressManager.json b/e2e/deployments/devnetL1/AddressManager.json new file mode 100644 index 000000000000..0d282320e1e1 --- /dev/null +++ b/e2e/deployments/devnetL1/AddressManager.json @@ -0,0 +1,253 @@ +{ + "abi": [ + { + "type": "function", + "name": "getAddress", + "inputs": [ + { + "name": "_name", + "type": "string", + "internalType": "string" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setAddress", + "inputs": [ + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "AddressSet", + "inputs": [ + { + "name": "name", + "type": "string", + "indexed": true, + "internalType": "string" + }, + { + "name": "newAddress", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "oldAddress", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x6a977Ade8B7908D159B0068cF74C55F292b9B4fe", + "args": [], + "bytecode": "0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105ef8061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "getAddress(string)": { + "params": { + "_name": "Name to retrieve an address for." + }, + "returns": { + "_0": "Address associated with the given name." + } + }, + "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." + }, + "setAddress(string,address)": { + "params": { + "_address": "Address to associate with the name.", + "_name": "String name to associate an address with." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "events": { + "AddressSet(string,address,address)": { + "params": { + "name": "String name being set in the registry.", + "newAddress": "Address set for the given name.", + "oldAddress": "Address that was previously set for the given name." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"oldAddress\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AddressSet\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAddress(string)\":{\"params\":{\"_name\":\"Name to retrieve an address for.\"},\"returns\":{\"_0\":\"Address associated with the given name.\"}},\"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.\"},\"setAddress(string,address)\":{\"params\":{\"_address\":\"Address to associate with the name.\",\"_name\":\"String name to associate an address with.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddress(string)\":{\"notice\":\"Retrieves the address associated with a given name.\"},\"setAddress(string,address)\":{\"notice\":\"Changes the address associated with a particular name.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/AddressManager.sol\":\"AddressManager\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xce90165ad572174eb5db03ed98282a4b6b76b136905131e50b65d8ed6eab5bf9", + "transactionIndex": "0x3", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x4a5fae", + "gasUsed": "0x62d28", + "contractAddress": "0x6a977Ade8B7908D159B0068cF74C55F292b9B4fe", + "logs": [ + { + "address": "0x6a977Ade8B7908D159B0068cF74C55F292b9B4fe", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be" + ], + "data": "0x", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0xce90165ad572174eb5db03ed98282a4b6b76b136905131e50b65d8ed6eab5bf9", + "transactionIndex": "0x3", + "logIndex": "0x2", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000001000000000000000000000000000000000000020000010000000000000808000000000000000000000000000000400001000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47128, + "contract": "src/legacy/AddressManager.sol:AddressManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 88416, + "contract": "src/legacy/AddressManager.sol:AddressManager", + "label": "addresses", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_address)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + }, + "transactionHash": "0xce90165ad572174eb5db03ed98282a4b6b76b136905131e50b65d8ed6eab5bf9", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "getAddress(string)": { + "notice": "Retrieves the address associated with a given name." + }, + "setAddress(string,address)": { + "notice": "Changes the address associated with a particular name." + } + }, + "events": { + "AddressSet(string,address,address)": { + "notice": "Emitted when an address is modified in the registry." + } + }, + "notice": "AddressManager is a legacy contract that was used in the old version of the Optimism system to manage a registry of string names to addresses. We now use a more standard proxy system instead, but this contract is still necessary for backwards compatibility with several older contracts." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/BlockOracle.json b/e2e/deployments/devnetL1/BlockOracle.json new file mode 100644 index 000000000000..27a311d0ceb8 --- /dev/null +++ b/e2e/deployments/devnetL1/BlockOracle.json @@ -0,0 +1,207 @@ +{ + "abi": [ + { + "type": "function", + "name": "checkpoint", + "inputs": [], + "outputs": [ + { + "name": "blockNumber_", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "load", + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "blockInfo_", + "type": "tuple", + "internalType": "struct BlockOracle.BlockInfo", + "components": [ + { + "name": "hash", + "type": "bytes32", + "internalType": "Hash" + }, + { + "name": "childTimestamp", + "type": "uint64", + "internalType": "Timestamp" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "Checkpoint", + "inputs": [ + { + "name": "blockNumber", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "blockHash", + "type": "bytes32", + "indexed": true, + "internalType": "Hash" + }, + { + "name": "childTimestamp", + "type": "uint64", + "indexed": true, + "internalType": "Timestamp" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "BlockHashNotPresent", + "inputs": [] + } + ], + "address": "0x042deb7f12Dad67215b7dD433f53B50C1C1bcb85", + "args": [], + "bytecode": "0x608060405234801561001057600080fd5b506102e7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806399d548aa14610098578063c2c4c5c1146100d0575b600080fd5b6100826040518060400160405280600581526020017f302e302e3100000000000000000000000000000000000000000000000000000081525081565b60405161008f9190610210565b60405180910390f35b6100ab6100a6366004610283565b6100e6565b604080518251815260209283015167ffffffffffffffff16928101929092520161008f565b6100d8610165565b60405190815260200161008f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610160576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600061017260014361029c565b60408051808201825282408082524267ffffffffffffffff81811660208086018281526000898152918290528782209651875551600190960180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016969093169590951790915593519495509093909291849186917fb67ff58b33060fd371a35ae2d9f1c3cdaec9b8197969f6efe2594a1ff4ba68c691a4505090565b600060208083528351808285015260005b8181101561023d57858101830151858201604001528201610221565b8181111561024f576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561029557600080fd5b5035919050565b6000828210156102d5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806399d548aa14610098578063c2c4c5c1146100d0575b600080fd5b6100826040518060400160405280600581526020017f302e302e3100000000000000000000000000000000000000000000000000000081525081565b60405161008f9190610210565b60405180910390f35b6100ab6100a6366004610283565b6100e6565b604080518251815260209283015167ffffffffffffffff16928101929092520161008f565b6100d8610165565b60405190815260200161008f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610160576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600061017260014361029c565b60408051808201825282408082524267ffffffffffffffff81811660208086018281526000898152918290528782209651875551600190960180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016969093169590951790915593519495509093909291849186917fb67ff58b33060fd371a35ae2d9f1c3cdaec9b8197969f6efe2594a1ff4ba68c691a4505090565b600060208083528351808285015260005b8181101561023d57858101830151858201604001528201610221565b8181111561024f576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561029557600080fd5b5035919050565b6000828210156102d5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "checkpoint()": { + "returns": { + "blockNumber_": "The block number that was checkpointed, which is always `block.number - 1`." + } + }, + "load(uint256)": { + "params": { + "_blockNumber": "The block number to load the block hash and timestamp for." + }, + "returns": { + "blockInfo_": "The block hash and timestamp for the given block number." + } + } + }, + "title": "BlockOracle" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"type\":\"error\",\"name\":\"BlockHashNotPresent\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"Hash\",\"name\":\"blockHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"Timestamp\",\"name\":\"childTimestamp\",\"type\":\"uint64\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Checkpoint\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"checkpoint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"load\",\"outputs\":[{\"internalType\":\"struct BlockOracle.BlockInfo\",\"name\":\"blockInfo_\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"Hash\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"internalType\":\"Timestamp\",\"name\":\"childTimestamp\",\"type\":\"uint64\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"checkpoint()\":{\"returns\":{\"blockNumber_\":\"The block number that was checkpointed, which is always `block.number - 1`.\"}},\"load(uint256)\":{\"params\":{\"_blockNumber\":\"The block number to load the block hash and timestamp for.\"},\"returns\":{\"blockInfo_\":\"The block hash and timestamp for the given block number.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"checkpoint()\":{\"notice\":\"Stores a block hash for the previous block number.\"},\"load(uint256)\":{\"notice\":\"Loads a block hash for a given block number, assuming that the block number has been stored in the oracle.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/dispute/BlockOracle.sol\":\"BlockOracle\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"src/dispute/BlockOracle.sol\":{\"keccak256\":\"0x2ab47226bc30d4bd33b6cac7ae60dfa053cbd6539fc0857fd8787d583a8fd68d\",\"urls\":[\"bzz-raw://d9790254415c0bacf491914c69eacae2a06d5f9a97a6378200c2bd1e0ddfca8f\",\"dweb:/ipfs/QmZStZ4rZcctPzo72BefUKaAzmNNX5u3zXvUf16HwKkWL6\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IBondManager.sol\":{\"keccak256\":\"0x31db84bf7a701125719c0bdaed316c8ec3d32e774a70b9bac3045d3ed272da8b\",\"urls\":[\"bzz-raw://35ef3970234b9a2d85ca800c5257398fd92a6959b0daa088b402a493ebf18d88\",\"dweb:/ipfs/QmWr1ZCBjRJPTUWyNcDv3G2Jb72cYG2p4rQA55WuUPUjao\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IDisputeGame.sol\":{\"keccak256\":\"0xd9cebb758474716504ba281e8c9e007ead5be676a835729c236afec47dfb1e7f\",\"urls\":[\"bzz-raw://fba945be8dbca576b6765fccc5fe8e31109562b0f2e9f943fc8b6c65fffc9829\",\"dweb:/ipfs/QmTWcBnmMhb3odqu2kkJbKZK7HNeiE7SvfD9tjKv8F4qWF\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IInitializable.sol\":{\"keccak256\":\"0xf021b03c9e887e227102b037595e0917b76546e796bec7aa4fdced61090267ce\",\"urls\":[\"bzz-raw://bcfbad382815e37355b7cc318fa333b9b5b08223d4315951fd0881430ab8d3df\",\"dweb:/ipfs/QmRng31WWpYeApQUcXJXhSdqL797drdtBwvUD6D9giCyy2\"],\"license\":\"MIT\"},\"src/dispute/lib/LibClock.sol\":{\"keccak256\":\"0x4599b150b8a3d53a9db22698666320e62261765e3ad5b58105bc93097b1a4690\",\"urls\":[\"bzz-raw://a0ab2d277fd4607510a5cafb91235a0fc3e47c3c0cdb45b2c185188ce888a1c5\",\"dweb:/ipfs/QmQ2bM3YmZCbN8uhKigSBh6j9VKrfxg61tjihwY7fdpARs\"],\"license\":\"MIT\"},\"src/dispute/lib/LibGameId.sol\":{\"keccak256\":\"0xa61b8562def4834607b733240e8eb4f924a75250df45852c9af1aea628f6b58d\",\"urls\":[\"bzz-raw://2853075b45f634db083ea5f495f0cb9c28eb2401e2c18fd5fb7bce2500ed78ad\",\"dweb:/ipfs/QmaJpEg5z6tZ3niZY6N3f8AZ89FRnUVZJHNUDs66sq97j6\"],\"license\":\"MIT\"},\"src/dispute/lib/LibHashing.sol\":{\"keccak256\":\"0x5a072cd028094eee55acb84ed8d08d7422b1fb46658b7e043e916781530a383b\",\"urls\":[\"bzz-raw://b67e54f1318f1fd67b28b16c6861a56e27217c26a12aaea5c446e2ec53143920\",\"dweb:/ipfs/QmVLSTP3PwXzRkR3A4qV9fjZhca9v8J1EnEYuVGUsSirAq\"],\"license\":\"MIT\"},\"src/dispute/lib/LibPosition.sol\":{\"keccak256\":\"0xccb2b2daeb72cafdd5a3b318043ea0a4795d2679728d275084731eefa2f1dc89\",\"urls\":[\"bzz-raw://69b71c71445d5bb770150d70cd5ae630e5df5fad5007620c28faa6d13db5063c\",\"dweb:/ipfs/QmY5TWPZdgziXF2oaaPpjuffboFddcDiKogsktYxFzi2LD\"],\"license\":\"MIT\"},\"src/libraries/DisputeErrors.sol\":{\"keccak256\":\"0xa8933cd2eb2b3e69fe93ce7ef97290fa89f7c3dc40e786c66e8b9ef4223617d4\",\"urls\":[\"bzz-raw://d227b64956cf1281a73eac5ec0876cad2e543443196096690b05ce1e921d7368\",\"dweb:/ipfs/QmfYQVZ9nW1hryhjqZz2vvR1aMr46kfPVybNhyDbbKo2R5\"],\"license\":\"MIT\"},\"src/libraries/DisputeTypes.sol\":{\"keccak256\":\"0xb7331579c5f9c29b9242a08ea3ab7cfa86eccabfbf19f30aa6b33e5da016adf3\",\"urls\":[\"bzz-raw://95e312750fa98e0f785131e951ed8d14577b18901dac7b63e1a6c8771796b9a8\",\"dweb:/ipfs/QmP4cYgHwW5d3wmKQkneNseSUYgPfQrmGRBEXen34iHTVy\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 84189, + "contract": "src/dispute/BlockOracle.sol:BlockOracle", + "label": "blocks", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_struct(BlockInfo)84172_storage)" + } + ], + "types": { + "t_mapping(t_uint256,t_struct(BlockInfo)84172_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct BlockOracle.BlockInfo)", + "numberOfBytes": "32", + "value": "t_struct(BlockInfo)84172_storage" + }, + "t_struct(BlockInfo)84172_storage": { + "encoding": "inplace", + "label": "struct BlockOracle.BlockInfo", + "numberOfBytes": "64", + "members": [ + { + "astId": 84168, + "contract": "src/dispute/BlockOracle.sol:BlockOracle", + "label": "hash", + "offset": 0, + "slot": "0", + "type": "t_userDefinedValueType(Hash)89991" + }, + { + "astId": 84171, + "contract": "src/dispute/BlockOracle.sol:BlockOracle", + "label": "childTimestamp", + "offset": 0, + "slot": "1", + "type": "t_userDefinedValueType(Timestamp)89999" + } + ] + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(Hash)89991": { + "encoding": "inplace", + "label": "Hash", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(Timestamp)89999": { + "encoding": "inplace", + "label": "Timestamp", + "numberOfBytes": "8" + } + } + }, + "transactionHash": "0x8aea6a70f5aa03ffd7f3f49f81ea5489401839bb66d6425ea29f24098d19d881", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "checkpoint()": { + "notice": "Stores a block hash for the previous block number." + }, + "load(uint256)": { + "notice": "Loads a block hash for a given block number, assuming that the block number has been stored in the oracle." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "Checkpoint(uint256,bytes32,uint64)": { + "notice": "Emitted when a block is checkpointed." + } + }, + "errors": { + "BlockHashNotPresent()": [ + { + "notice": "Thrown when a block hash is attempted to be loaded that has not been stored." + } + ] + }, + "notice": "Stores a map of block numbers => block hashes for use in dispute resolution" + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/DisputeGameFactory.json b/e2e/deployments/devnetL1/DisputeGameFactory.json new file mode 100644 index 000000000000..45d1e2cdbfa9 --- /dev/null +++ b/e2e/deployments/devnetL1/DisputeGameFactory.json @@ -0,0 +1,637 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "create", + "inputs": [ + { + "name": "_gameType", + "type": "uint8", + "internalType": "GameType" + }, + { + "name": "_rootClaim", + "type": "bytes32", + "internalType": "Claim" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "proxy_", + "type": "address", + "internalType": "contract IDisputeGame" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "gameAtIndex", + "inputs": [ + { + "name": "_index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "gameType_", + "type": "uint8", + "internalType": "GameType" + }, + { + "name": "timestamp_", + "type": "uint64", + "internalType": "Timestamp" + }, + { + "name": "proxy_", + "type": "address", + "internalType": "contract IDisputeGame" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "gameCount", + "inputs": [], + "outputs": [ + { + "name": "gameCount_", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "gameImpls", + "inputs": [ + { + "name": "", + "type": "uint8", + "internalType": "GameType" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IDisputeGame" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "games", + "inputs": [ + { + "name": "_gameType", + "type": "uint8", + "internalType": "GameType" + }, + { + "name": "_rootClaim", + "type": "bytes32", + "internalType": "Claim" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "proxy_", + "type": "address", + "internalType": "contract IDisputeGame" + }, + { + "name": "timestamp_", + "type": "uint64", + "internalType": "Timestamp" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getGameUUID", + "inputs": [ + { + "name": "_gameType", + "type": "uint8", + "internalType": "GameType" + }, + { + "name": "_rootClaim", + "type": "bytes32", + "internalType": "Claim" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "uuid_", + "type": "bytes32", + "internalType": "Hash" + } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setImplementation", + "inputs": [ + { + "name": "_gameType", + "type": "uint8", + "internalType": "GameType" + }, + { + "name": "_impl", + "type": "address", + "internalType": "contract IDisputeGame" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "DisputeGameCreated", + "inputs": [ + { + "name": "disputeProxy", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "gameType", + "type": "uint8", + "indexed": true, + "internalType": "GameType" + }, + { + "name": "rootClaim", + "type": "bytes32", + "indexed": true, + "internalType": "Claim" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ImplementationSet", + "inputs": [ + { + "name": "impl", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "gameType", + "type": "uint8", + "indexed": true, + "internalType": "GameType" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "GameAlreadyExists", + "inputs": [ + { + "name": "uuid", + "type": "bytes32", + "internalType": "Hash" + } + ] + }, + { + "type": "error", + "name": "NoImplementation", + "inputs": [ + { + "name": "gameType", + "type": "uint8", + "internalType": "GameType" + } + ] + } + ], + "address": "0x1D76cd1460239F99516F165578b6A80EFb70f3C6", + "args": [], + "bytecode": "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b6200097e1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b6024820152600080516020620012d183398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b6024820152600080516020620012d183398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b61102f80620002a26000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c4d66de81161005b578063c4d66de8146102e8578063dfa162d3146102fb578063f2fde38b1461033157600080fd5b80638da5cb5b14610231578063bb8aa1fc1461024f578063c49d5271146102a057600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a61461022957600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610d45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610e2e565b610344565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004610ed7565b6105a6565b005b606754610178565b61021c6040518060400160405280600581526020017f302e302e3600000000000000000000000000000000000000000000000000000081525081565b6040516101829190610f0e565b6101d661062d565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b61026261025d366004610f81565b610641565b6040805160ff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610182565b6102b36102ae366004610e2e565b6106a3565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610182565b6101d66102f6366004610f9a565b61072b565b61019e610309366004610fbe565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d661033f366004610f9a565b6108c7565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806103ae576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b6104118585856040516020016103c693929190610fd9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff83169061099a565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561045b57600080fd5b505af115801561046f573d6000803e3d6000fd5b5050505060006104b6878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60008181526066602052604090205490915015610502576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016103a5565b60004260b81b60f889901b178417600083815260666020526040808220839055606780546001810182559083527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae0183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b6105ae610ace565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b610635610ace565b61063f6000610b4f565b565b60008060006106966067858154811061065c5761065c610ff3565b906000526020600020015460f881901c9167ffffffffffffffff60b883901c169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b60008060006106e9878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60009081526066602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860b89190911c67ffffffffffffffff16975095505050505050565b600054610100900460ff161580801561074b5750600054600160ff909116105b806107655750303b158015610765575060005460ff166001145b6107f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016103a5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561084f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610857610bc6565b61086082610b4f565b80156108c357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6108cf610ace565b73ffffffffffffffffffffffffffffffffffffffff8116610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a5565b61097b81610b4f565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610a5257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610a15565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610abf577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff16331461063f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103a5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103a5565b61063f600054610100900460ff16610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103a5565b61063f33610b4f565b803560ff81168114610d1157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610d5a57600080fd5b610d6384610d00565b925060208401359150604084013567ffffffffffffffff80821115610d8757600080fd5b818601915086601f830112610d9b57600080fd5b813581811115610dad57610dad610d16565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610df357610df3610d16565b81604052828152896020848701011115610e0c57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610e4457600080fd5b610e4d85610d00565b935060208501359250604085013567ffffffffffffffff80821115610e7157600080fd5b818701915087601f830112610e8557600080fd5b813581811115610e9457600080fd5b886020828501011115610ea657600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461097b57600080fd5b60008060408385031215610eea57600080fd5b610ef383610d00565b91506020830135610f0381610eb5565b809150509250929050565b600060208083528351808285015260005b81811015610f3b57858101830151858201604001528201610f1f565b81811115610f4d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f9357600080fd5b5035919050565b600060208284031215610fac57600080fd5b8135610fb781610eb5565b9392505050565b600060208284031215610fd057600080fd5b610fb782610d00565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c4d66de81161005b578063c4d66de8146102e8578063dfa162d3146102fb578063f2fde38b1461033157600080fd5b80638da5cb5b14610231578063bb8aa1fc1461024f578063c49d5271146102a057600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a61461022957600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610d45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610e2e565b610344565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004610ed7565b6105a6565b005b606754610178565b61021c6040518060400160405280600581526020017f302e302e3600000000000000000000000000000000000000000000000000000081525081565b6040516101829190610f0e565b6101d661062d565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b61026261025d366004610f81565b610641565b6040805160ff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610182565b6102b36102ae366004610e2e565b6106a3565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610182565b6101d66102f6366004610f9a565b61072b565b61019e610309366004610fbe565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d661033f366004610f9a565b6108c7565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806103ae576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b6104118585856040516020016103c693929190610fd9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff83169061099a565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561045b57600080fd5b505af115801561046f573d6000803e3d6000fd5b5050505060006104b6878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60008181526066602052604090205490915015610502576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016103a5565b60004260b81b60f889901b178417600083815260666020526040808220839055606780546001810182559083527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae0183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b6105ae610ace565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b610635610ace565b61063f6000610b4f565b565b60008060006106966067858154811061065c5761065c610ff3565b906000526020600020015460f881901c9167ffffffffffffffff60b883901c169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b60008060006106e9878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60009081526066602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860b89190911c67ffffffffffffffff16975095505050505050565b600054610100900460ff161580801561074b5750600054600160ff909116105b806107655750303b158015610765575060005460ff166001145b6107f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016103a5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561084f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610857610bc6565b61086082610b4f565b80156108c357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6108cf610ace565b73ffffffffffffffffffffffffffffffffffffffff8116610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a5565b61097b81610b4f565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610a5257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610a15565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610abf577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff16331461063f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103a5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103a5565b61063f600054610100900460ff16610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103a5565b61063f33610b4f565b803560ff81168114610d1157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610d5a57600080fd5b610d6384610d00565b925060208401359150604084013567ffffffffffffffff80821115610d8757600080fd5b818601915086601f830112610d9b57600080fd5b813581811115610dad57610dad610d16565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610df357610df3610d16565b81604052828152896020848701011115610e0c57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610e4457600080fd5b610e4d85610d00565b935060208501359250604085013567ffffffffffffffff80821115610e7157600080fd5b818701915087601f830112610e8557600080fd5b813581811115610e9457600080fd5b886020828501011115610ea657600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461097b57600080fd5b60008060408385031215610eea57600080fd5b610ef383610d00565b91506020830135610f0381610eb5565b809150509250929050565b600060208083528351808285015260005b81811015610f3b57858101830151858201604001528201610f1f565b81811115610f4d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f9357600080fd5b5035919050565b600060208284031215610fac57600080fd5b8135610fb781610eb5565b9392505050565b600060208284031215610fd057600080fd5b610fb782610d00565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "create(uint8,bytes32,bytes)": { + "params": { + "_extraData": "Any extra data that should be provided to the created dispute game.", + "_gameType": "The type of the DisputeGame - used to decide the proxy implementation.", + "_rootClaim": "The root claim of the DisputeGame." + }, + "returns": { + "proxy_": "The address of the created DisputeGame proxy." + } + }, + "gameAtIndex(uint256)": { + "params": { + "_index": "The index of the dispute game." + }, + "returns": { + "gameType_": "The type of the DisputeGame - used to decide the proxy implementation.", + "proxy_": "The clone of the `DisputeGame` created with the given parameters. Returns `address(0)` if nonexistent.", + "timestamp_": "The timestamp of the creation of the dispute game." + } + }, + "gameCount()": { + "returns": { + "gameCount_": "The total number of dispute games created by this factory." + } + }, + "games(uint8,bytes32,bytes)": { + "details": "`++` equates to concatenation.", + "params": { + "_extraData": "Any extra data that should be provided to the created dispute game.", + "_gameType": "The type of the DisputeGame - used to decide the proxy implementation", + "_rootClaim": "The root claim of the DisputeGame." + }, + "returns": { + "proxy_": "The clone of the `DisputeGame` created with the given parameters. Returns `address(0)` if nonexistent.", + "timestamp_": "The timestamp of the creation of the dispute game." + } + }, + "getGameUUID(uint8,bytes32,bytes)": { + "details": "Hashes the concatenation of `gameType . rootClaim . extraData` without expanding memory.", + "params": { + "_extraData": "Any extra data that should be provided to the created dispute game.", + "_gameType": "The type of the DisputeGame.", + "_rootClaim": "The root claim of the DisputeGame." + }, + "returns": { + "uuid_": "The unique identifier for the given dispute game parameters." + } + }, + "initialize(address)": { + "params": { + "_owner": "The owner of the contract." + } + }, + "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." + }, + "setImplementation(uint8,address)": { + "details": "May only be called by the `owner`.", + "params": { + "_gameType": "The type of the DisputeGame.", + "_impl": "The implementation contract for the given `GameType`." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "errors": { + "GameAlreadyExists(bytes32)": [ + { + "params": { + "uuid": "The UUID of the dispute game that already exists." + } + } + ], + "NoImplementation(uint8)": [ + { + "params": { + "gameType": "The unsupported game type." + } + } + ] + }, + "title": "DisputeGameFactory" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid\",\"type\":\"bytes32\"}],\"type\":\"error\",\"name\":\"GameAlreadyExists\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"type\":\"error\",\"name\":\"NoImplementation\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"disputeProxy\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"DisputeGameCreated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"impl\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ImplementationSet\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"create\",\"outputs\":[{\"internalType\":\"contract IDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gameAtIndex\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint8\"},{\"internalType\":\"Timestamp\",\"name\":\"timestamp_\",\"type\":\"uint64\"},{\"internalType\":\"contract IDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gameCount_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gameImpls\",\"outputs\":[{\"internalType\":\"contract IDisputeGame\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"games\",\"outputs\":[{\"internalType\":\"contract IDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"Timestamp\",\"name\":\"timestamp_\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getGameUUID\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid_\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"contract IDisputeGame\",\"name\":\"_impl\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setImplementation\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"create(uint8,bytes32,bytes)\":{\"params\":{\"_extraData\":\"Any extra data that should be provided to the created dispute game.\",\"_gameType\":\"The type of the DisputeGame - used to decide the proxy implementation.\",\"_rootClaim\":\"The root claim of the DisputeGame.\"},\"returns\":{\"proxy_\":\"The address of the created DisputeGame proxy.\"}},\"gameAtIndex(uint256)\":{\"params\":{\"_index\":\"The index of the dispute game.\"},\"returns\":{\"gameType_\":\"The type of the DisputeGame - used to decide the proxy implementation.\",\"proxy_\":\"The clone of the `DisputeGame` created with the given parameters. Returns `address(0)` if nonexistent.\",\"timestamp_\":\"The timestamp of the creation of the dispute game.\"}},\"gameCount()\":{\"returns\":{\"gameCount_\":\"The total number of dispute games created by this factory.\"}},\"games(uint8,bytes32,bytes)\":{\"details\":\"`++` equates to concatenation.\",\"params\":{\"_extraData\":\"Any extra data that should be provided to the created dispute game.\",\"_gameType\":\"The type of the DisputeGame - used to decide the proxy implementation\",\"_rootClaim\":\"The root claim of the DisputeGame.\"},\"returns\":{\"proxy_\":\"The clone of the `DisputeGame` created with the given parameters. Returns `address(0)` if nonexistent.\",\"timestamp_\":\"The timestamp of the creation of the dispute game.\"}},\"getGameUUID(uint8,bytes32,bytes)\":{\"details\":\"Hashes the concatenation of `gameType . rootClaim . extraData` without expanding memory.\",\"params\":{\"_extraData\":\"Any extra data that should be provided to the created dispute game.\",\"_gameType\":\"The type of the DisputeGame.\",\"_rootClaim\":\"The root claim of the DisputeGame.\"},\"returns\":{\"uuid_\":\"The unique identifier for the given dispute game parameters.\"}},\"initialize(address)\":{\"params\":{\"_owner\":\"The owner of the contract.\"}},\"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.\"},\"setImplementation(uint8,address)\":{\"details\":\"May only be called by the `owner`.\",\"params\":{\"_gameType\":\"The type of the DisputeGame.\",\"_impl\":\"The implementation contract for the given `GameType`.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"constructs a new DisputeGameFactory contract.\"},\"create(uint8,bytes32,bytes)\":{\"notice\":\"Creates a new DisputeGame proxy contract.\"},\"gameAtIndex(uint256)\":{\"notice\":\"`gameAtIndex` returns the dispute game contract address and its creation timestamp at the given index. Each created dispute game increments the underlying index.\"},\"gameCount()\":{\"notice\":\"The total number of dispute games created by this factory.\"},\"gameImpls(uint8)\":{\"notice\":\"`gameImpls` is a mapping that maps `GameType`s to their respective `IDisputeGame` implementations.\"},\"games(uint8,bytes32,bytes)\":{\"notice\":\"`games` queries an internal mapping that maps the hash of `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone.\"},\"getGameUUID(uint8,bytes32,bytes)\":{\"notice\":\"Returns a unique identifier for the given dispute game parameters.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"setImplementation(uint8,address)\":{\"notice\":\"Sets the implementation contract for a specific `GameType`.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/dispute/DisputeGameFactory.sol\":\"DisputeGameFactory\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/clones-with-immutable-args/src/ClonesWithImmutableArgs.sol\":{\"keccak256\":\"0x220db41bfceb0146f86e9be87d3d954fd1d52eadcb3bbfc5cd89e5543a46fd1e\",\"urls\":[\"bzz-raw://19155470db05e2e67a8c14f21cc903bb4833d8e5d248c2183073320c8a595705\",\"dweb:/ipfs/QmTchpXE8MMH1XcYxaZvx64UiVzBatbWy7Sw5HFhVJJjxi\"],\"license\":\"BSD\"},\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"src/dispute/DisputeGameFactory.sol\":{\"keccak256\":\"0xb2db064d41020f43a185ed72d763dd0effd518b72cf77564f6a2dce95448a460\",\"urls\":[\"bzz-raw://de0b42901f7e17493f40db3dd7b42c2d2d8cfe406076f85c5430cb9bbeb6f5bb\",\"dweb:/ipfs/QmXjMpLet6vTdtq6KuEVxo5Xm45wixsb4pTGyf3Et8iBK3\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IBondManager.sol\":{\"keccak256\":\"0x31db84bf7a701125719c0bdaed316c8ec3d32e774a70b9bac3045d3ed272da8b\",\"urls\":[\"bzz-raw://35ef3970234b9a2d85ca800c5257398fd92a6959b0daa088b402a493ebf18d88\",\"dweb:/ipfs/QmWr1ZCBjRJPTUWyNcDv3G2Jb72cYG2p4rQA55WuUPUjao\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IDisputeGame.sol\":{\"keccak256\":\"0xd9cebb758474716504ba281e8c9e007ead5be676a835729c236afec47dfb1e7f\",\"urls\":[\"bzz-raw://fba945be8dbca576b6765fccc5fe8e31109562b0f2e9f943fc8b6c65fffc9829\",\"dweb:/ipfs/QmTWcBnmMhb3odqu2kkJbKZK7HNeiE7SvfD9tjKv8F4qWF\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IDisputeGameFactory.sol\":{\"keccak256\":\"0x9e525966fe0583cc20376a654542eec946ebd86a2802456678b5dc837c0ebf1f\",\"urls\":[\"bzz-raw://e26eeb1479653eabbb00318dd4d9c46fdf76fe93b6c8ba7420c793b69a3cc871\",\"dweb:/ipfs/QmVq6Zvv5SVK8pYxvfjyi7nK2jtxmQmupix3TNeaMcBJ6g\"],\"license\":\"MIT\"},\"src/dispute/interfaces/IInitializable.sol\":{\"keccak256\":\"0xf021b03c9e887e227102b037595e0917b76546e796bec7aa4fdced61090267ce\",\"urls\":[\"bzz-raw://bcfbad382815e37355b7cc318fa333b9b5b08223d4315951fd0881430ab8d3df\",\"dweb:/ipfs/QmRng31WWpYeApQUcXJXhSdqL797drdtBwvUD6D9giCyy2\"],\"license\":\"MIT\"},\"src/dispute/lib/LibClock.sol\":{\"keccak256\":\"0x4599b150b8a3d53a9db22698666320e62261765e3ad5b58105bc93097b1a4690\",\"urls\":[\"bzz-raw://a0ab2d277fd4607510a5cafb91235a0fc3e47c3c0cdb45b2c185188ce888a1c5\",\"dweb:/ipfs/QmQ2bM3YmZCbN8uhKigSBh6j9VKrfxg61tjihwY7fdpARs\"],\"license\":\"MIT\"},\"src/dispute/lib/LibGameId.sol\":{\"keccak256\":\"0xa61b8562def4834607b733240e8eb4f924a75250df45852c9af1aea628f6b58d\",\"urls\":[\"bzz-raw://2853075b45f634db083ea5f495f0cb9c28eb2401e2c18fd5fb7bce2500ed78ad\",\"dweb:/ipfs/QmaJpEg5z6tZ3niZY6N3f8AZ89FRnUVZJHNUDs66sq97j6\"],\"license\":\"MIT\"},\"src/dispute/lib/LibHashing.sol\":{\"keccak256\":\"0x5a072cd028094eee55acb84ed8d08d7422b1fb46658b7e043e916781530a383b\",\"urls\":[\"bzz-raw://b67e54f1318f1fd67b28b16c6861a56e27217c26a12aaea5c446e2ec53143920\",\"dweb:/ipfs/QmVLSTP3PwXzRkR3A4qV9fjZhca9v8J1EnEYuVGUsSirAq\"],\"license\":\"MIT\"},\"src/dispute/lib/LibPosition.sol\":{\"keccak256\":\"0xccb2b2daeb72cafdd5a3b318043ea0a4795d2679728d275084731eefa2f1dc89\",\"urls\":[\"bzz-raw://69b71c71445d5bb770150d70cd5ae630e5df5fad5007620c28faa6d13db5063c\",\"dweb:/ipfs/QmY5TWPZdgziXF2oaaPpjuffboFddcDiKogsktYxFzi2LD\"],\"license\":\"MIT\"},\"src/libraries/DisputeErrors.sol\":{\"keccak256\":\"0xa8933cd2eb2b3e69fe93ce7ef97290fa89f7c3dc40e786c66e8b9ef4223617d4\",\"urls\":[\"bzz-raw://d227b64956cf1281a73eac5ec0876cad2e543443196096690b05ce1e921d7368\",\"dweb:/ipfs/QmfYQVZ9nW1hryhjqZz2vvR1aMr46kfPVybNhyDbbKo2R5\"],\"license\":\"MIT\"},\"src/libraries/DisputeTypes.sol\":{\"keccak256\":\"0xb7331579c5f9c29b9242a08ea3ab7cfa86eccabfbf19f30aa6b33e5da016adf3\",\"urls\":[\"bzz-raw://95e312750fa98e0f785131e951ed8d14577b18901dac7b63e1a6c8771796b9a8\",\"dweb:/ipfs/QmP4cYgHwW5d3wmKQkneNseSUYgPfQrmGRBEXen34iHTVy\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 44768, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 44771, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 46299, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 44640, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 44760, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 84305, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "gameImpls", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_userDefinedValueType(GameType)90009,t_contract(IDisputeGame)87463)" + }, + { + "astId": 84312, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "_disputeGames", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_userDefinedValueType(Hash)89991,t_userDefinedValueType(GameId)90003)" + }, + { + "astId": 84317, + "contract": "src/dispute/DisputeGameFactory.sol:DisputeGameFactory", + "label": "_disputeGameList", + "offset": 0, + "slot": "103", + "type": "t_array(t_userDefinedValueType(GameId)90003)dyn_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_array(t_userDefinedValueType(GameId)90003)dyn_storage": { + "encoding": "dynamic_array", + "label": "GameId[]", + "numberOfBytes": "32", + "base": "t_userDefinedValueType(GameId)90003" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IDisputeGame)87463": { + "encoding": "inplace", + "label": "contract IDisputeGame", + "numberOfBytes": "20" + }, + "t_mapping(t_userDefinedValueType(GameType)90009,t_contract(IDisputeGame)87463)": { + "encoding": "mapping", + "key": "t_userDefinedValueType(GameType)90009", + "label": "mapping(GameType => contract IDisputeGame)", + "numberOfBytes": "32", + "value": "t_contract(IDisputeGame)87463" + }, + "t_mapping(t_userDefinedValueType(Hash)89991,t_userDefinedValueType(GameId)90003)": { + "encoding": "mapping", + "key": "t_userDefinedValueType(Hash)89991", + "label": "mapping(Hash => GameId)", + "numberOfBytes": "32", + "value": "t_userDefinedValueType(GameId)90003" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + }, + "t_userDefinedValueType(GameId)90003": { + "encoding": "inplace", + "label": "GameId", + "numberOfBytes": "32" + }, + "t_userDefinedValueType(GameType)90009": { + "encoding": "inplace", + "label": "GameType", + "numberOfBytes": "1" + }, + "t_userDefinedValueType(Hash)89991": { + "encoding": "inplace", + "label": "Hash", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0x399134f1e13add8ff98f22d6a51fe9f7d2aa8fb5a41a7eed0bc9f07cbd15bd6f", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "constructor": { + "notice": "constructs a new DisputeGameFactory contract." + }, + "create(uint8,bytes32,bytes)": { + "notice": "Creates a new DisputeGame proxy contract." + }, + "gameAtIndex(uint256)": { + "notice": "`gameAtIndex` returns the dispute game contract address and its creation timestamp at the given index. Each created dispute game increments the underlying index." + }, + "gameCount()": { + "notice": "The total number of dispute games created by this factory." + }, + "gameImpls(uint8)": { + "notice": "`gameImpls` is a mapping that maps `GameType`s to their respective `IDisputeGame` implementations." + }, + "games(uint8,bytes32,bytes)": { + "notice": "`games` queries an internal mapping that maps the hash of `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone." + }, + "getGameUUID(uint8,bytes32,bytes)": { + "notice": "Returns a unique identifier for the given dispute game parameters." + }, + "initialize(address)": { + "notice": "Initializes the contract." + }, + "setImplementation(uint8,address)": { + "notice": "Sets the implementation contract for a specific `GameType`." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "DisputeGameCreated(address,uint8,bytes32)": { + "notice": "Emitted when a new dispute game is created" + }, + "ImplementationSet(address,uint8)": { + "notice": "Emitted when a new game implementation added to the factory" + } + }, + "errors": { + "GameAlreadyExists(bytes32)": [ + { + "notice": "Thrown when a dispute game that already exists is attempted to be created." + } + ], + "NoImplementation(uint8)": [ + { + "notice": "Thrown when a dispute game is attempted to be created with an unsupported game type." + } + ] + }, + "notice": "A factory contract for creating `IDisputeGame` contracts. All created dispute games are stored in both a mapping and an append only array. The timestamp of the creation time of the dispute game is packed tightly into the storage slot with the address of the dispute game. This is to make offchain discoverability of playable dispute games easier." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/DisputeGameFactoryProxy.json b/e2e/deployments/devnetL1/DisputeGameFactoryProxy.json new file mode 100644 index 000000000000..0ed4ff1d4a6f --- /dev/null +++ b/e2e/deployments/devnetL1/DisputeGameFactoryProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0xe67575204500AA637a013Db8fF9610940CACf9E6", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x583e8c1f08b3db2c067b1841b58c76d0d3d85aa766f6638ec5eebe0affe87593", + "transactionIndex": "0x3", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x1c554e", + "gasUsed": "0x80250", + "contractAddress": "0xe67575204500AA637a013Db8fF9610940CACf9E6", + "logs": [ + { + "address": "0xe67575204500AA637a013Db8fF9610940CACf9E6", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "transactionHash": "0x583e8c1f08b3db2c067b1841b58c76d0d3d85aa766f6638ec5eebe0affe87593", + "transactionIndex": "0x3", + "logIndex": "0x2", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc6ef3dc7" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x583e8c1f08b3db2c067b1841b58c76d0d3d85aa766f6638ec5eebe0affe87593", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1CrossDomainMessenger.json b/e2e/deployments/devnetL1/L1CrossDomainMessenger.json new file mode 100644 index 000000000000..2ca93c33de20 --- /dev/null +++ b/e2e/deployments/devnetL1/L1CrossDomainMessenger.json @@ -0,0 +1,822 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_portal", + "type": "address", + "internalType": "contract OptimismPortal" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "MESSAGE_VERSION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint16", + "internalType": "uint16" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MIN_GAS_CALLDATA_OVERHEAD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "OTHER_MESSENGER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PORTAL", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract OptimismPortal" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "RELAY_CALL_OVERHEAD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "RELAY_CONSTANT_OVERHEAD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "RELAY_GAS_CHECK_BUFFER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "RELAY_RESERVED_GAS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "baseGas", + "inputs": [ + { + "name": "_message", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "failedMessages", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_superchainConfig", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "messageNonce", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "portal", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "relayMessage", + "inputs": [ + { + "name": "_nonce", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_sender", + "type": "address", + "internalType": "address" + }, + { + "name": "_target", + "type": "address", + "internalType": "address" + }, + { + "name": "_value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_message", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "sendMessage", + "inputs": [ + { + "name": "_target", + "type": "address", + "internalType": "address" + }, + { + "name": "_message", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "successfulMessages", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "superchainConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "xDomainMessageSender", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "FailedRelayedMessage", + "inputs": [ + { + "name": "msgHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RelayedMessage", + "inputs": [ + { + "name": "msgHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SentMessage", + "inputs": [ + { + "name": "target", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "message", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + }, + { + "name": "messageNonce", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "gasLimit", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SentMessageExtension1", + "inputs": [ + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + } + ], + "address": "0x4C944cc9E0D5C58726FAc6b883A2C8016f49eCFd", + "args": [ + "0x4859725d8f2f49aE689512eE5F150FdcB76cd72c" + ], + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200223d3803806200223d833981016040819052620000349162000269565b7342000000000000000000000000000000000000076080526001600160a01b03811660a0526200006560006200006c565b506200029b565b600054600160a81b900460ff16158080156200009557506000546001600160a01b90910460ff16105b80620000cc5750620000b230620001d560201b620014771760201c565b158015620000cc5750600054600160a01b900460ff166001145b620001355760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000163576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b0319166001600160a01b03841617905562000188620001e4565b8015620001d1576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002535760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200012c565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200027c57600080fd5b81516001600160a01b03811681146200029457600080fd5b9392505050565b60805160a051611f4b620002f2600039600081816101d401528181610350015281816114d00152818161167d015281816116de01526117aa0152600081816103b2015281816104f101526116a70152611f4b6000f3fe6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "baseGas(bytes,uint32)": { + "params": { + "_message": "Message to compute the amount of required gas for.", + "_minGasLimit": "Minimum desired gas limit when message goes to target." + }, + "returns": { + "_0": "Amount of gas required to guarantee message receipt." + } + }, + "constructor": { + "params": { + "_portal": "Address of the OptimismPortal contract on this network." + } + }, + "initialize(address)": { + "params": { + "_superchainConfig": "Address of the SuperchainConfig contract on this network." + } + }, + "messageNonce()": { + "returns": { + "_0": "Nonce of the next message to be sent, with added message version." + } + }, + "paused()": { + "returns": { + "_0": "Whether or not the contract is paused." + } + }, + "relayMessage(uint256,address,address,uint256,uint256,bytes)": { + "params": { + "_message": "Message to send to the target.", + "_minGasLimit": "Minimum amount of gas that the message can be executed with.", + "_nonce": "Nonce of the message being relayed.", + "_sender": "Address of the user who sent the message.", + "_target": "Address that the message is targeted at.", + "_value": "ETH value to send with the message." + } + }, + "sendMessage(address,bytes,uint32)": { + "params": { + "_message": "Message to trigger the target address with.", + "_minGasLimit": "Minimum gas limit that the message can be executed with.", + "_target": "Target contract or wallet address." + } + }, + "xDomainMessageSender()": { + "returns": { + "_0": "Address of the sender of the currently executing message on the other chain." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"FailedRelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessageExtension1\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"portal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"relayMessage\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"sendMessage\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract on this network.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal. This will be removed in the future, use `portal` instead.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"constructor\":{\"notice\":\"Constructs the L1CrossDomainMessenger contract.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"portal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1CrossDomainMessenger.sol\":\"L1CrossDomainMessenger\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0x9df7a928c47b13e5762d37319b4b3632e2e19b4c8dba10209f7db53e6d9a05a2\",\"urls\":[\"bzz-raw://fd3d7c6503dc4572750dde44decce8e3b772e156456e33da6c8d560ddbc8b37d\",\"dweb:/ipfs/Qmes7MhyEdRweVzdEPWSYcScDbyKHpg2qxYK6dvsy4R2uU\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0x663fc35cd5af00e3e2ccbf57f1865a73cd717116f04c5bd89c5b131ae21c54d7\",\"urls\":[\"bzz-raw://0f4ad3864a4382d932fa8d75dd8b9bb189c45fc7a9b25a73bfdd7a2774a3e158\",\"dweb:/ipfs/QmYCKtRp1WQGFiWu4HcLWJmKwNeYiRoborXQcT8kx3c7P8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 94935, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_0_0_20", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 44768, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "_initialized", + "offset": 20, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 44771, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "_initializing", + "offset": 21, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 94942, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_1_0_1600", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 94945, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_51_0_20", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 94950, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_52_0_1568", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 94953, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_101_0_1", + "offset": 0, + "slot": "101", + "type": "t_bool" + }, + { + "astId": 94958, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_102_0_1568", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 94961, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_151_0_32", + "offset": 0, + "slot": "151", + "type": "t_uint256" + }, + { + "astId": 94966, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_152_0_1568", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 94971, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_201_0_32", + "offset": 0, + "slot": "201", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 94976, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "spacer_202_0_32", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 95024, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "successfulMessages", + "offset": 0, + "slot": "203", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 95027, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "xDomainMsgSender", + "offset": 0, + "slot": "204", + "type": "t_address" + }, + { + "astId": 95030, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "msgNonce", + "offset": 0, + "slot": "205", + "type": "t_uint240" + }, + { + "astId": 95035, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "failedMessages", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 95040, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "__gap", + "offset": 0, + "slot": "207", + "type": "t_array(t_uint256)44_storage" + }, + { + "astId": 75585, + "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", + "label": "superchainConfig", + "offset": 0, + "slot": "251", + "type": "t_contract(SuperchainConfig)78483" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)44_storage": { + "encoding": "inplace", + "label": "uint256[44]", + "numberOfBytes": "1408", + "base": "t_uint256" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(SuperchainConfig)78483": { + "encoding": "inplace", + "label": "contract SuperchainConfig", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint240": { + "encoding": "inplace", + "label": "uint240", + "numberOfBytes": "30" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x2ccda74008d69a885d1d9ca06e222e43fd5ac2d3ff6b971f1b30329970ea2fdc", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "MESSAGE_VERSION()": { + "notice": "Current message version identifier." + }, + "MIN_GAS_CALLDATA_OVERHEAD()": { + "notice": "Extra gas added to base gas for each byte of calldata in a message." + }, + "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()": { + "notice": "Denominator for dynamic overhead added to the base gas for a message." + }, + "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()": { + "notice": "Numerator for dynamic overhead added to the base gas for a message." + }, + "OTHER_MESSENGER()": { + "notice": "Address of the paired CrossDomainMessenger contract on the other chain." + }, + "PORTAL()": { + "notice": "Address of the OptimismPortal. This will be removed in the future, use `portal` instead." + }, + "RELAY_CALL_OVERHEAD()": { + "notice": "Gas reserved for performing the external call in `relayMessage`." + }, + "RELAY_CONSTANT_OVERHEAD()": { + "notice": "Constant overhead added to the base gas for a message." + }, + "RELAY_GAS_CHECK_BUFFER()": { + "notice": "Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`." + }, + "RELAY_RESERVED_GAS()": { + "notice": "Gas reserved for finalizing the execution of `relayMessage` after the safe call." + }, + "baseGas(bytes,uint32)": { + "notice": "Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely." + }, + "constructor": { + "notice": "Constructs the L1CrossDomainMessenger contract." + }, + "failedMessages(bytes32)": { + "notice": "Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt." + }, + "initialize(address)": { + "notice": "Initializes the contract." + }, + "messageNonce()": { + "notice": "Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures." + }, + "paused()": { + "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." + }, + "portal()": { + "notice": "Getter for the OptimismPortal address." + }, + "relayMessage(uint256,address,address,uint256,uint256,bytes)": { + "notice": "Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed." + }, + "sendMessage(address,bytes,uint32)": { + "notice": "Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function)." + }, + "successfulMessages(bytes32)": { + "notice": "Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again." + }, + "superchainConfig()": { + "notice": "Address of the SuperchainConfig contract." + }, + "version()": { + "notice": "Semantic version." + }, + "xDomainMessageSender()": { + "notice": "Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it." + } + }, + "events": { + "FailedRelayedMessage(bytes32)": { + "notice": "Emitted whenever a message fails to be relayed on this chain." + }, + "RelayedMessage(bytes32)": { + "notice": "Emitted whenever a message is successfully relayed on this chain." + }, + "SentMessage(address,address,bytes,uint256,uint256)": { + "notice": "Emitted whenever a message is sent to the other chain." + }, + "SentMessageExtension1(address,uint256)": { + "notice": "Additional event data to emit, required as of Bedrock. Cannot be merged with the SentMessage event without breaking the ABI of this contract, this is good enough." + } + }, + "notice": "The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible for sending and receiving data on the L1 side. Users are encouraged to use this interface instead of interacting with lower-level contracts directly." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1CrossDomainMessengerProxy.json b/e2e/deployments/devnetL1/L1CrossDomainMessengerProxy.json new file mode 100644 index 000000000000..8d7124de2fc2 --- /dev/null +++ b/e2e/deployments/devnetL1/L1CrossDomainMessengerProxy.json @@ -0,0 +1,116 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_addressManager", + "type": "address", + "internalType": "contract AddressManager" + }, + { + "name": "_implementationName", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + } + ], + "address": "0x926Eb09E87Af7c492502ceD62D1eD3a192DcB816", + "args": "[\"0x6a977Ade8B7908D159B0068cF74C55F292b9B4fe\",\"\\OVM_L1CrossDomainMessenger\\\"]", + "bytecode": "0x608060405234801561001057600080fd5b506040516105f03803806105f083398101604081905261002f91610088565b30600090815260016020908152604080832080546001600160a01b0319166001600160a01b03871617905590829052902061006a8282610203565b5050506102c2565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561009b57600080fd5b82516001600160a01b03811681146100b257600080fd5b602084810151919350906001600160401b03808211156100d157600080fd5b818601915086601f8301126100e557600080fd5b8151818111156100f7576100f7610072565b604051601f8201601f19908116603f0116810190838211818310171561011f5761011f610072565b81604052828152898684870101111561013757600080fd5b600093505b82841015610159578484018601518185018701529285019261013c565b8284111561016a5760008684830101525b8096505050505050509250929050565b600181811c9082168061018e57607f821691505b6020821081036101ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101fe57600081815260208120601f850160051c810160208610156101db5750805b601f850160051c820191505b818110156101fa578281556001016101e7565b5050505b505050565b81516001600160401b0381111561021c5761021c610072565b6102308161022a845461017a565b846101b4565b602080601f831160018114610265576000841561024d5750858301515b600019600386901b1c1916600185901b1785556101fa565b600085815260208120601f198616915b8281101561029457888601518255948401946001909101908401610275565b50858210156102b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61031f806102d16000396000f3fe608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_addressManager": "Address of the AddressManager.", + "_implementationName": "implementationName of the contract to proxy to." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_addressManager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_implementationName\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_addressManager\":\"Address of the AddressManager.\",\"_implementationName\":\"implementationName of the contract to proxy to.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/ResolvedDelegateProxy.sol\":\"ResolvedDelegateProxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/ResolvedDelegateProxy.sol\":{\"keccak256\":\"0x33425509c2982627f1e88977d76637096322954c474217bd4d03a3244814f332\",\"urls\":[\"bzz-raw://2cb3702c3c280ebf65e636b2d2fd8533aebae69014304014353afee129415c53\",\"dweb:/ipfs/QmYpcVwF8hzwCcPqv535oENbars988N21MVvvDw9eQNaSf\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x2a05466b90d8d412e042e99f4929fed1a9ca83f655aaad76fe6c17d1b246f757", + "transactionIndex": "0x0", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x44e5e", + "gasUsed": "0x44e5e", + "contractAddress": "0x926Eb09E87Af7c492502ceD62D1eD3a192DcB816", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc6ef3dc7" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 89351, + "contract": "src/legacy/ResolvedDelegateProxy.sol:ResolvedDelegateProxy", + "label": "implementationName", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_string_storage)" + }, + { + "astId": 89357, + "contract": "src/legacy/ResolvedDelegateProxy.sol:ResolvedDelegateProxy", + "label": "addressManager", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_contract(AddressManager)88492)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(AddressManager)88492": { + "encoding": "inplace", + "label": "contract AddressManager", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_contract(AddressManager)88492)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => contract AddressManager)", + "numberOfBytes": "32", + "value": "t_contract(AddressManager)88492" + }, + "t_mapping(t_address,t_string_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0x2a05466b90d8d412e042e99f4929fed1a9ca83f655aaad76fe6c17d1b246f757", + "userdoc": { + "version": 1, + "kind": "user", + "notice": "ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to resolve the implementation address. We're maintaining this contract for backwards compatibility so we can manage all legacy proxies where necessary." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1ERC721Bridge.json b/e2e/deployments/devnetL1/L1ERC721Bridge.json new file mode 100644 index 000000000000..83d47dcc175b --- /dev/null +++ b/e2e/deployments/devnetL1/L1ERC721Bridge.json @@ -0,0 +1,580 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_messenger", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "MESSENGER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract CrossDomainMessenger" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "OTHER_BRIDGE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bridgeERC721", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_tokenId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "bridgeERC721To", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_tokenId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "deposits", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "finalizeBridgeERC721", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_from", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_tokenId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_superchainConfig", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "messenger", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract CrossDomainMessenger" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "otherBridge", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "superchainConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ERC721BridgeFinalized", + "inputs": [ + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "tokenId", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ERC721BridgeInitiated", + "inputs": [ + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "tokenId", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + } + ], + "address": "0x68AAdfB734CC053065f815e6f20c0A55774757a4", + "args": [ + "0x926Eb09E87Af7c492502ceD62D1eD3a192DcB816" + ], + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200168a3803806200168a83398101604081905262000034916200029f565b807342000000000000000000000000000000000000146001600160a01b038216620000bb5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200012b5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000b2565b6001600160a01b039182166080521660a05262000149600062000150565b50620002d1565b600054610100900460ff1615808015620001715750600054600160ff909116105b80620001a157506200018e306200029060201b62000b5c1760201c565b158015620001a1575060005460ff166001145b620002065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000b2565b6000805460ff1916600117905580156200022a576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b03841617905580156200028c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600060208284031215620002b257600080fd5b81516001600160a01b0381168114620002ca57600080fd5b9392505050565b60805160a051611362620003286000396000818161020b0152818161027c015281816104270152610e0401526000818161013a01528181610232015281816103fd0152818161045e0152610dd501526113626000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063761f449311610081578063aa5574521161005b578063aa55745214610254578063c4d66de814610267578063c89701a21461027a57600080fd5b8063761f4493146101f35780637f46ddb214610206578063927ede2d1461022d57600080fd5b806354fd4d50116100b257806354fd4d501461015e5780635c975abb146101a75780635d93a3fc146101bf57600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610f76565b6102a0565b005b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b61019a6040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611064565b6101af61034c565b604051901515815260200161011a565b6101af6101cd36600461107e565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6101366102013660046110bf565b6103e5565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b610136610262366004611157565b6108d5565b6101366102753660046111ce565b610991565b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b333b15610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103448686333388888888610b78565b505050505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156103bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e091906111eb565b905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561050357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104eb919061120d565b73ffffffffffffffffffffffffffffffffffffffff16145b61058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161032b565b61059761034c565b156105fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161032b565b3073ffffffffffffffffffffffffffffffffffffffff8816036106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561083257600080fd5b505af1158015610846573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516108c49493929190611273565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161032b565b6109888787338888888888610b78565b50505050505050565b600054610100900460ff16158080156109b15750600054600160ff909116105b806109cb5750303b1580156109cb575060005460ff166001145b610a57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610ab557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015610b5857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161032b565b600063761f449360e01b888a8989898888604051602401610c4297969594939291906112b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d8257600080fd5b505af1158015610d96573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610e30907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611310565b600060405180830381600087803b158015610e4a57600080fd5b505af1158015610e5e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610edc9493929190611273565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1157600080fd5b50565b803563ffffffff81168114610f2857600080fd5b919050565b60008083601f840112610f3f57600080fd5b50813567ffffffffffffffff811115610f5757600080fd5b602083019150836020828501011115610f6f57600080fd5b9250929050565b60008060008060008060a08789031215610f8f57600080fd5b8635610f9a81610eef565b95506020870135610faa81610eef565b945060408701359350610fbf60608801610f14565b9250608087013567ffffffffffffffff811115610fdb57600080fd5b610fe789828a01610f2d565b979a9699509497509295939492505050565b6000815180845260005b8181101561101f57602081850181015186830182015201611003565b81811115611031576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006110776020830184610ff9565b9392505050565b60008060006060848603121561109357600080fd5b833561109e81610eef565b925060208401356110ae81610eef565b929592945050506040919091013590565b600080600080600080600060c0888a0312156110da57600080fd5b87356110e581610eef565b965060208801356110f581610eef565b9550604088013561110581610eef565b9450606088013561111581610eef565b93506080880135925060a088013567ffffffffffffffff81111561113857600080fd5b6111448a828b01610f2d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561117257600080fd5b873561117d81610eef565b9650602088013561118d81610eef565b9550604088013561119d81610eef565b9450606088013593506111b260808901610f14565b925060a088013567ffffffffffffffff81111561113857600080fd5b6000602082840312156111e057600080fd5b813561107781610eef565b6000602082840312156111fd57600080fd5b8151801515811461107757600080fd5b60006020828403121561121f57600080fd5b815161107781610eef565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006112a960608301848661122a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261130360c08301848661122a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061133f6060830185610ff9565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c8063761f449311610081578063aa5574521161005b578063aa55745214610254578063c4d66de814610267578063c89701a21461027a57600080fd5b8063761f4493146101f35780637f46ddb214610206578063927ede2d1461022d57600080fd5b806354fd4d50116100b257806354fd4d501461015e5780635c975abb146101a75780635d93a3fc146101bf57600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610f76565b6102a0565b005b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b61019a6040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611064565b6101af61034c565b604051901515815260200161011a565b6101af6101cd36600461107e565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6101366102013660046110bf565b6103e5565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b610136610262366004611157565b6108d5565b6101366102753660046111ce565b610991565b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b333b15610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103448686333388888888610b78565b505050505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156103bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e091906111eb565b905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561050357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104eb919061120d565b73ffffffffffffffffffffffffffffffffffffffff16145b61058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161032b565b61059761034c565b156105fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161032b565b3073ffffffffffffffffffffffffffffffffffffffff8816036106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561083257600080fd5b505af1158015610846573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516108c49493929190611273565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161032b565b6109888787338888888888610b78565b50505050505050565b600054610100900460ff16158080156109b15750600054600160ff909116105b806109cb5750303b1580156109cb575060005460ff166001145b610a57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610ab557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015610b5857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161032b565b600063761f449360e01b888a8989898888604051602401610c4297969594939291906112b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d8257600080fd5b505af1158015610d96573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610e30907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611310565b600060405180830381600087803b158015610e4a57600080fd5b505af1158015610e5e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610edc9493929190611273565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1157600080fd5b50565b803563ffffffff81168114610f2857600080fd5b919050565b60008083601f840112610f3f57600080fd5b50813567ffffffffffffffff811115610f5757600080fd5b602083019150836020828501011115610f6f57600080fd5b9250929050565b60008060008060008060a08789031215610f8f57600080fd5b8635610f9a81610eef565b95506020870135610faa81610eef565b945060408701359350610fbf60608801610f14565b9250608087013567ffffffffffffffff811115610fdb57600080fd5b610fe789828a01610f2d565b979a9699509497509295939492505050565b6000815180845260005b8181101561101f57602081850181015186830182015201611003565b81811115611031576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006110776020830184610ff9565b9392505050565b60008060006060848603121561109357600080fd5b833561109e81610eef565b925060208401356110ae81610eef565b929592945050506040919091013590565b600080600080600080600060c0888a0312156110da57600080fd5b87356110e581610eef565b965060208801356110f581610eef565b9550604088013561110581610eef565b9450606088013561111581610eef565b93506080880135925060a088013567ffffffffffffffff81111561113857600080fd5b6111448a828b01610f2d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561117257600080fd5b873561117d81610eef565b9650602088013561118d81610eef565b9550604088013561119d81610eef565b9450606088013593506111b260808901610f14565b925060a088013567ffffffffffffffff81111561113857600080fd5b6000602082840312156111e057600080fd5b813561107781610eef565b6000602082840312156111fd57600080fd5b8151801515811461107757600080fd5b60006020828403121561121f57600080fd5b815161107781610eef565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006112a960608301848661122a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261130360c08301848661122a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061133f6060830185610ff9565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "bridgeERC721(address,address,uint256,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", + "_localToken": "Address of the ERC721 on this domain.", + "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", + "_remoteToken": "Address of the ERC721 on the remote domain.", + "_tokenId": "Token ID to bridge." + } + }, + "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", + "_localToken": "Address of the ERC721 on this domain.", + "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", + "_remoteToken": "Address of the ERC721 on the remote domain.", + "_to": "Address to receive the token on the other domain.", + "_tokenId": "Token ID to bridge." + } + }, + "constructor": { + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network." + } + }, + "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { + "params": { + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_from": "Address that triggered the bridge on the other domain.", + "_localToken": "Address of the ERC721 token on this domain.", + "_remoteToken": "Address of the ERC721 token on the other domain.", + "_to": "Address to receive the token on this domain.", + "_tokenId": "ID of the token being deposited." + } + }, + "initialize(address)": { + "params": { + "_superchainConfig": "Address of the SuperchainConfig contract on this network." + } + }, + "messenger()": { + "returns": { + "_0": "Messenger contract on this domain." + } + }, + "otherBridge()": { + "returns": { + "_0": "Address of the bridge on the other network." + } + }, + "paused()": { + "returns": { + "_0": "Whether or not the contract is paused." + } + } + }, + "title": "L1ERC721Bridge" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721To\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC721\"},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_to\":\"Address to receive the token on the other domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_from\":\"Address that triggered the bridge on the other domain.\",\"_localToken\":\"Address of the ERC721 token on this domain.\",\"_remoteToken\":\"Address of the ERC721 token on the other domain.\",\"_to\":\"Address to receive the token on this domain.\",\"_tokenId\":\"ID of the token being deposited.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain. This will be removed in the future, use `messenger` instead.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead.\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"constructor\":{\"notice\":\"Constructs the L1ERC721Bridge contract.\"},\"deposits(address,address,uint256)\":{\"notice\":\"Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token.\"},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"notice\":\"Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Legacy getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Legacy getter for other bridge address.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0x533c336296674ded2bde8d3ca4a8b75d535732bbca50d065f8687246170a9c37\",\"urls\":[\"bzz-raw://281df98c7080584720850c67449d3a97736320ff41ba6151d919e963e8a7ac00\",\"dweb:/ipfs/QmVqBHoLygqn7PWcEq3taTH9WHnsr1pPWi2ferwrf7dPHz\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0x55561c9ff8fa5c2436c03c7da90dfb9c46523b77c7992481bc7487415bcbfb46\",\"urls\":[\"bzz-raw://5c1fb7b3e06cca1555ecca7a523d7fd9f7482114f680e663387925b05616ab64\",\"dweb:/ipfs/QmRXVR1jfYWfBAXWrr8aMS9mMaLtrmckR2agJkrq32TVkV\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ERC721Bridge.sol\":{\"keccak256\":\"0x70aacc49b94ab1f43a5737046ee0b95b8774a3756d0f2d2fcfdedc541ae9344a\",\"urls\":[\"bzz-raw://cbc8abe6b65c32cfec535a7bb080ad20963ffd91682718477cb5be3990bf4e06\",\"dweb:/ipfs/QmeBZRzZrSYVN1jiS9ohEMaNM9WgL9FuivC6tcvipZ9rv7\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xb3a65b067e67a9e1fa0493401c8d247970377c6725eba4e7b02ce8099c4f4f52\",\"urls\":[\"bzz-raw://86bb6864027560ade2f4ced6a6e34213cbff8002977dc365377e5a0b473cf17b\",\"dweb:/ipfs/QmQvjtodTK27as1g1PzsYk9NyJJ3X6a6251o1vrBwx7DPT\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47332, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 47335, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 95498, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)48_storage" + }, + { + "astId": 75760, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "deposits", + "offset": 0, + "slot": "49", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" + }, + { + "astId": 75764, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "superchainConfig", + "offset": 0, + "slot": "50", + "type": "t_contract(SuperchainConfig)78483" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)48_storage": { + "encoding": "inplace", + "label": "uint256[48]", + "numberOfBytes": "1536", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(SuperchainConfig)78483": { + "encoding": "inplace", + "label": "contract SuperchainConfig", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_bool)" + }, + "t_mapping(t_uint256,t_bool)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x9b958f27ba15ad42b872d4c2161f8d8827106b2b8068aac556cb3d8156922275", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "MESSENGER()": { + "notice": "Messenger contract on this domain. This will be removed in the future, use `messenger` instead." + }, + "OTHER_BRIDGE()": { + "notice": "Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead." + }, + "bridgeERC721(address,address,uint256,uint32,bytes)": { + "notice": "Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." + }, + "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { + "notice": "Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." + }, + "constructor": { + "notice": "Constructs the L1ERC721Bridge contract." + }, + "deposits(address,address,uint256)": { + "notice": "Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token." + }, + "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { + "notice": "Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain." + }, + "initialize(address)": { + "notice": "Initializes the contract." + }, + "messenger()": { + "notice": "Legacy getter for messenger contract." + }, + "otherBridge()": { + "notice": "Legacy getter for other bridge address." + }, + "paused()": { + "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." + }, + "superchainConfig()": { + "notice": "Address of the SuperchainConfig contract." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC721 bridge from the other network is finalized." + }, + "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC721 bridge to the other network is initiated." + } + }, + "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as an escrow for ERC721 tokens deposited into L2." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1ERC721BridgeProxy.json b/e2e/deployments/devnetL1/L1ERC721BridgeProxy.json new file mode 100644 index 000000000000..d608211d9166 --- /dev/null +++ b/e2e/deployments/devnetL1/L1ERC721BridgeProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0xE9E587fBDdA42B07458ACb22d1af14B313015De7", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x05c25185caefb2983241c19d4a855be145bee4c0b37608916369e7f91f1806c6", + "transactionIndex": "0x2", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x1452fe", + "gasUsed": "0x80250", + "contractAddress": "0xE9E587fBDdA42B07458ACb22d1af14B313015De7", + "logs": [ + { + "address": "0xE9E587fBDdA42B07458ACb22d1af14B313015De7", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "transactionHash": "0x05c25185caefb2983241c19d4a855be145bee4c0b37608916369e7f91f1806c6", + "transactionIndex": "0x2", + "logIndex": "0x1", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000004000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc6ef3dc7" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x05c25185caefb2983241c19d4a855be145bee4c0b37608916369e7f91f1806c6", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1StandardBridge.json b/e2e/deployments/devnetL1/L1StandardBridge.json new file mode 100644 index 000000000000..51f711e2f690 --- /dev/null +++ b/e2e/deployments/devnetL1/L1StandardBridge.json @@ -0,0 +1,1186 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_messenger", + "type": "address", + "internalType": "address payable" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "MESSENGER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract CrossDomainMessenger" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "OTHER_BRIDGE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract StandardBridge" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bridgeERC20", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "bridgeERC20To", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "bridgeETH", + "inputs": [ + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "bridgeETHTo", + "inputs": [ + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "depositERC20", + "inputs": [ + { + "name": "_l1Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_l2Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositERC20To", + "inputs": [ + { + "name": "_l1Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_l2Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositETH", + "inputs": [ + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "depositETHTo", + "inputs": [ + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_minGasLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "deposits", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "finalizeBridgeERC20", + "inputs": [ + { + "name": "_localToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_from", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "finalizeBridgeETH", + "inputs": [ + { + "name": "_from", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "finalizeERC20Withdrawal", + "inputs": [ + { + "name": "_l1Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_l2Token", + "type": "address", + "internalType": "address" + }, + { + "name": "_from", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "finalizeETHWithdrawal", + "inputs": [ + { + "name": "_from", + "type": "address", + "internalType": "address" + }, + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_extraData", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_superchainConfig", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "l2TokenBridge", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "messenger", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract CrossDomainMessenger" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "otherBridge", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract StandardBridge" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "superchainConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ERC20BridgeFinalized", + "inputs": [ + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ERC20BridgeInitiated", + "inputs": [ + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ERC20DepositInitiated", + "inputs": [ + { + "name": "l1Token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "l2Token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ERC20WithdrawalFinalized", + "inputs": [ + { + "name": "l1Token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "l2Token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ETHBridgeFinalized", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ETHBridgeInitiated", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ETHDepositInitiated", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ETHWithdrawalFinalized", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "extraData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + } + ], + "address": "0x0D5cE1Fc6BEb4Ec209C61fFb911d020b4eFeC242", + "args": [ + "0x926Eb09E87Af7c492502ceD62D1eD3a192DcB816" + ], + "bytecode": "0x60c06040523480156200001157600080fd5b5060405162002eed38038062002eed8339810160408190526200003491620001be565b6001600160a01b03811660805273420000000000000000000000000000000000001060a0526200006560006200006c565b50620001f0565b600054610100900460ff16158080156200008d5750600054600160ff909116105b80620000bd5750620000aa30620001af60201b6200056f1760201c565b158015620000bd575060005460ff166001145b620001255760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000149576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790558015620001ab576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600060208284031215620001d157600080fd5b81516001600160a01b0381168114620001e957600080fd5b9392505050565b60805160a051612c7c62000271600039600081816103e70152818161049e015281816105e001528181610b30015281816117070152611db90152600081816102f6015281816104d4015281816105b60152818161061701528181610b0601528181610b6701528181610e63015281816116ca0152611d7d0152612c7c6000f3fe6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "bridgeERC20(address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of local tokens to deposit.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_localToken": "Address of the ERC20 on this chain.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_remoteToken": "Address of the corresponding token on the remote chain." + } + }, + "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of local tokens to deposit.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_localToken": "Address of the ERC20 on this chain.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_remoteToken": "Address of the corresponding token on the remote chain.", + "_to": "Address of the receiver." + } + }, + "bridgeETH(uint32,bytes)": { + "params": { + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." + } + }, + "bridgeETHTo(address,uint32,bytes)": { + "params": { + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_to": "Address of the receiver." + } + }, + "constructor": { + "params": { + "_messenger": "Address of the L1CrossDomainMessenger." + } + }, + "depositERC20(address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to deposit.", + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_l1Token": "Address of the L1 token being deposited.", + "_l2Token": "Address of the corresponding token on L2.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2." + } + }, + "depositERC20To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to deposit.", + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_l1Token": "Address of the L1 token being deposited.", + "_l2Token": "Address of the corresponding token on L2.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2.", + "_to": "Address of the recipient on L2." + } + }, + "depositETH(uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2." + } + }, + "depositETHTo(address,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2.", + "_to": "Address of the recipient on L2." + } + }, + "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of the ERC20 being bridged.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_from": "Address of the sender.", + "_localToken": "Address of the ERC20 on this chain.", + "_remoteToken": "Address of the corresponding token on the remote chain.", + "_to": "Address of the receiver." + } + }, + "finalizeBridgeETH(address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of ETH being bridged.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_from": "Address of the sender.", + "_to": "Address of the receiver." + } + }, + "finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to withdraw.", + "_extraData": "Optional data forwarded from L2.", + "_from": "Address of the withdrawer on L2.", + "_l1Token": "Address of the token on L1.", + "_l2Token": "Address of the corresponding token on L2.", + "_to": "Address of the recipient on L1." + } + }, + "finalizeETHWithdrawal(address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of ETH to withdraw.", + "_extraData": "Optional data forwarded from L2.", + "_from": "Address of the withdrawer on L2.", + "_to": "Address of the recipient on L1." + } + }, + "initialize(address)": { + "params": { + "_superchainConfig": "Address of the SuperchainConfig contract on this network." + } + }, + "l2TokenBridge()": { + "returns": { + "_0": "Address of the corresponding L2 bridge contract." + } + }, + "messenger()": { + "returns": { + "_0": "Messenger contract on this domain." + } + }, + "otherBridge()": { + "returns": { + "_0": "The bridge contract on the other network." + } + }, + "paused()": { + "returns": { + "_0": "Whether or not the contract is paused." + } + } + }, + "events": { + "ERC20DepositInitiated(address,address,address,address,uint256,bytes)": { + "params": { + "amount": "Amount of the ERC20 deposited.", + "extraData": "Extra data attached to the deposit.", + "from": "Address of the depositor.", + "l1Token": "Address of the token on L1.", + "l2Token": "Address of the corresponding token on L2.", + "to": "Address of the recipient on L2." + } + }, + "ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)": { + "params": { + "amount": "Amount of the ERC20 withdrawn.", + "extraData": "Extra data attached to the withdrawal.", + "from": "Address of the withdrawer.", + "l1Token": "Address of the token on L1.", + "l2Token": "Address of the corresponding token on L2.", + "to": "Address of the recipient on L1." + } + }, + "ETHDepositInitiated(address,address,uint256,bytes)": { + "params": { + "amount": "Amount of ETH deposited.", + "extraData": "Extra data attached to the deposit.", + "from": "Address of the depositor.", + "to": "Address of the recipient on L2." + } + }, + "ETHWithdrawalFinalized(address,address,uint256,bytes)": { + "params": { + "amount": "Amount of ETH withdrawn.", + "extraData": "Extra data attached to the withdrawal.", + "from": "Address of the withdrawer.", + "to": "Address of the recipient on L1." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20DepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHDepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHWithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeBridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeERC20Withdrawal\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeETHWithdrawal\"},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the L1CrossDomainMessenger.\"}},\"depositERC20(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into the sender's account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositERC20To(address,address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into a target account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"depositETH(uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into the sender's account on L2.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositETHTo(address,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into a target account on L2. Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will be locked in the L2StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ERC20 tokens from L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_l1Token\":\"Address of the token on L1.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"finalizeETHWithdrawal(address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ETH from L2.\",\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"l2TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L2 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L2 bridge contract.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"The bridge contract on the other network.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"constructor\":{\"notice\":\"Constructs the L1StandardBridge contract.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Getter for the other bridge.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1StandardBridge.sol\":\"L1StandardBridge\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x2564decacc35545e2de52ea7793ceaa561ec4bc86fdd9d56b41c199cd6bca7ef\",\"urls\":[\"bzz-raw://6231b05c0c581b04536ac968ce053a99312d24e35defcd64b4f2cb8540ffe268\",\"dweb:/ipfs/QmRrq2Sguo4CyMyy8KPyXsGe4ULQr8Tm3919eRsvs3yPte\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/StandardBridge.sol\":{\"keccak256\":\"0x84b8925a791503b39861a9bf692e45d149053922b1339abe4d13b633121f0493\",\"urls\":[\"bzz-raw://b71e4723358644d72b35442530abdbdfcb425d807c675ba0bf94c2b95632bff2\",\"dweb:/ipfs/QmaKMD4wkAdiGGBhG49AN62jzD5F5PLWcNKjMasLwyN2WE\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47332, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 47335, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 97519, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "spacer_0_2_20", + "offset": 2, + "slot": "0", + "type": "t_address" + }, + { + "astId": 97522, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "spacer_1_0_20", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 97529, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "deposits", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 97534, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "__gap", + "offset": 0, + "slot": "3", + "type": "t_array(t_uint256)47_storage" + }, + { + "astId": 76060, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "superchainConfig", + "offset": 0, + "slot": "50", + "type": "t_contract(SuperchainConfig)78483" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)47_storage": { + "encoding": "inplace", + "label": "uint256[47]", + "numberOfBytes": "1504", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(SuperchainConfig)78483": { + "encoding": "inplace", + "label": "contract SuperchainConfig", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x96cf80d6cef1ec6b7590208e852f52aba1d2af596a634abfac259d3553bea863", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "MESSENGER()": { + "notice": "Messenger contract on this domain." + }, + "OTHER_BRIDGE()": { + "notice": "Corresponding bridge on the other domain." + }, + "bridgeERC20(address,address,uint256,uint32,bytes)": { + "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." + }, + "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { + "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." + }, + "bridgeETH(uint32,bytes)": { + "notice": "Sends ETH to the sender's address on the other chain." + }, + "bridgeETHTo(address,uint32,bytes)": { + "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." + }, + "constructor": { + "notice": "Constructs the L1StandardBridge contract." + }, + "deposits(address,address)": { + "notice": "Mapping that stores deposits for a given pair of local and remote tokens." + }, + "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { + "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." + }, + "finalizeBridgeETH(address,address,uint256,bytes)": { + "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." + }, + "initialize(address)": { + "notice": "Initializes the contract." + }, + "messenger()": { + "notice": "Getter for messenger contract." + }, + "otherBridge()": { + "notice": "Getter for the other bridge." + }, + "paused()": { + "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." + }, + "superchainConfig()": { + "notice": "Address of the SuperchainConfig contract." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC20 bridge is finalized on this chain." + }, + "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC20 bridge is initiated to the other chain." + }, + "ETHBridgeFinalized(address,address,uint256,bytes)": { + "notice": "Emitted when an ETH bridge is finalized on this chain." + }, + "ETHBridgeInitiated(address,address,uint256,bytes)": { + "notice": "Emitted when an ETH bridge is initiated to the other chain." + } + }, + "notice": "The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L1, it will be escrowed within this contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was stored within this contract. After Bedrock, ETH is instead stored inside the OptimismPortal contract. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L1StandardBridgeProxy.json b/e2e/deployments/devnetL1/L1StandardBridgeProxy.json new file mode 100644 index 000000000000..3d06feb65195 --- /dev/null +++ b/e2e/deployments/devnetL1/L1StandardBridgeProxy.json @@ -0,0 +1,182 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "getImplementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getOwner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setCode", + "inputs": [ + { + "name": "_code", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setOwner", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setStorage", + "inputs": [ + { + "name": "_key", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_value", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } + ], + "address": "0xe50ea86676B29448a4e586511d8920105cEd1159", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a44380380610a4483398101604081905261002f9161005d565b610057817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b5061008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b6109a88061009c6000396000f3fe60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_owner": "Address of the initial contract owner." + } + }, + "getImplementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "getOwner()": { + "returns": { + "_0": "Owner address." + } + }, + "setCode(bytes)": { + "params": { + "_code": "New contract code to run inside this contract." + } + }, + "setOwner(address)": { + "params": { + "_owner": "New owner of the proxy contract." + } + }, + "setStorage(bytes32,bytes32)": { + "params": { + "_key": "Storage key to modify.", + "_value": "New value for the storage key." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_code\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setCode\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setOwner\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_value\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setStorage\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_owner\":\"Address of the initial contract owner.\"}},\"getImplementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"getOwner()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"setCode(bytes)\":{\"params\":{\"_code\":\"New contract code to run inside this contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"New owner of the proxy contract.\"}},\"setStorage(bytes32,bytes32)\":{\"params\":{\"_key\":\"Storage key to modify.\",\"_value\":\"New value for the storage key.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getImplementation()\":{\"notice\":\"Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"getOwner()\":{\"notice\":\"Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"setCode(bytes)\":{\"notice\":\"Sets the code that should be running behind this proxy. Note: This scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner.\"},\"setOwner(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"setStorage(bytes32,bytes32)\":{\"notice\":\"Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/L1ChugSplashProxy.sol\":\"L1ChugSplashProxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0xdde5626645fa217ad3a37805c4c3012e4251de01df868aae73b986f5d03cdb23\",\"urls\":[\"bzz-raw://a99fd0ec440c17c826465001dc88c5185dd41dc72396254fdd3cdfcc84aeae8c\",\"dweb:/ipfs/QmStHuecN89zBL8FH9SUK1TtkyYwfzMY2KkQaFJLHZLuyA\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xea98dbde04e9883194d003afed8b67d0bd261d11d45fe46281320bb9f25ad93d", + "transactionIndex": "0x10", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0xac15bf", + "gasUsed": "0x94b82", + "contractAddress": "0xe50ea86676B29448a4e586511d8920105cEd1159", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0xea98dbde04e9883194d003afed8b67d0bd261d11d45fe46281320bb9f25ad93d", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "getImplementation()": { + "notice": "Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." + }, + "getOwner()": { + "notice": "Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." + }, + "setCode(bytes)": { + "notice": "Sets the code that should be running behind this proxy. Note: This scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner." + }, + "setOwner(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "setStorage(bytes32,bytes32)": { + "notice": "Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner." + } + }, + "notice": "Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added functions `setCode` and `setStorage` for changing the code or storage of the contract. Note for future developers: do NOT make anything in this contract 'public' unless you know what you're doing. Anything public can potentially have a function signature that conflicts with a signature attached to the implementation contract. Public functions SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good reason not to have that modifier. And there almost certainly is not a good reason to not have that modifier. Beware!" + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L2OutputOracle.json b/e2e/deployments/devnetL1/L2OutputOracle.json new file mode 100644 index 000000000000..cfc7c75df660 --- /dev/null +++ b/e2e/deployments/devnetL1/L2OutputOracle.json @@ -0,0 +1,816 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_submissionInterval", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_l2BlockTime", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_startingBlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_startingTimestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_proposer", + "type": "address", + "internalType": "address" + }, + { + "name": "_challenger", + "type": "address", + "internalType": "address" + }, + { + "name": "_finalizationPeriodSeconds", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "CHALLENGER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "FINALIZATION_PERIOD_SECONDS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "L2_BLOCK_TIME", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PROPOSER", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "SUBMISSION_INTERVAL", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "challenger", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "computeL2Timestamp", + "inputs": [ + { + "name": "_l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "deleteL2Outputs", + "inputs": [ + { + "name": "_l2OutputIndex", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "finalizationPeriodSeconds", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getL2Output", + "inputs": [ + { + "name": "_l2OutputIndex", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct Types.OutputProposal", + "components": [ + { + "name": "outputRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "timestamp", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "l2BlockNumber", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getL2OutputAfter", + "inputs": [ + { + "name": "_l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct Types.OutputProposal", + "components": [ + { + "name": "outputRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "timestamp", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "l2BlockNumber", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getL2OutputIndexAfter", + "inputs": [ + { + "name": "_l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_startingBlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_startingTimestamp", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "l2BlockTime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "latestBlockNumber", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "latestOutputIndex", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "nextBlockNumber", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "nextOutputIndex", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proposeL2Output", + "inputs": [ + { + "name": "_outputRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_l2BlockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_l1BlockHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_l1BlockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "proposer", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "startingBlockNumber", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "startingTimestamp", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "submissionInterval", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OutputProposed", + "inputs": [ + { + "name": "outputRoot", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "l2OutputIndex", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "l2BlockNumber", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "l1Timestamp", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OutputsDeleted", + "inputs": [ + { + "name": "prevNextOutputIndex", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "newNextOutputIndex", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + } + ], + "address": "0x4E9dB5E7dA19Dcd10931B5C30482b9aF671CE841", + "args": [ + "10", + "1", + "0", + "0", + "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + "2" + ], + "bytecode": "0x6101206040523480156200001257600080fd5b506040516200198438038062001984833981016040819052620000359162000347565b60008611620000b15760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008711620001295760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000a8565b608087905260a08690526001600160a01b0380841660e052821660c05261010081905262000158858562000165565b50505050505050620003af565b600054610100900460ff1615808015620001865750600054600160ff909116105b80620001b65750620001a3306200031b60201b6200133c1760201c565b158015620001b6575060005460ff166001145b6200021b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a8565b6000805460ff1916600117905580156200023f576000805461ff0019166101001790555b42821115620002c55760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000a8565b60028290556001839055801562000316576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200034257600080fd5b919050565b600080600080600080600060e0888a0312156200036357600080fd5b875196506020880151955060408801519450606088015193506200038a608089016200032a565b92506200039a60a089016200032a565b915060c0880151905092959891949750929550565b60805160a05160c05160e0516101005161154a6200043a600039600081816104ad0152818161058b01526109c90152600081816104460152818161047c0152610b3901526000818161022e0152818161030501526108630152600081816101a1015281816103a401526110700152600081816101fd0152818161053501526110be015261154a6000f3fe60806040526004361061018a5760003560e01c806393991af3116100d6578063cf8e5cf01161007f578063e1a41bcf11610059578063e1a41bcf14610526578063e4a3011614610559578063f4daa2911461057957600080fd5b8063cf8e5cf0146104d1578063d1de856c146104f1578063dcec33481461051157600080fd5b8063a8e4fb90116100b0578063a8e4fb9014610437578063bffa7f0f1461046a578063ce5db8d61461049e57600080fd5b806393991af3146103955780639aaab648146103c8578063a25ae557146103db57600080fd5b80636abcf563116101385780637f006420116101125780637f0064201461033d578063887862721461035d57806389c44cbb1461037357600080fd5b80636abcf563146102de5780636b4d98dd146102f357806370872aa51461032757600080fd5b8063534db0e211610169578063534db0e21461021f57806354fd4d501461027357806369f16eec146102c957600080fd5b80622134cc1461018f5780634599c788146101d6578063529933df146101eb575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101c36105ad565b3480156101f757600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561022b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611358565b3480156102d557600080fd5b506101c3610620565b3480156102ea57600080fd5b506003546101c3565b3480156102ff57600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033357600080fd5b506101c360015481565b34801561034957600080fd5b506101c36103583660046113cb565b610632565b34801561036957600080fd5b506101c360025481565b34801561037f57600080fd5b5061039361038e3660046113cb565b61084b565b005b3480156103a157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6103936103d63660046113e4565b610b21565b3480156103e757600080fd5b506103fb6103f63660046113cb565b610fa0565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561044357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b34801561047657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104aa57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104dd57600080fd5b506103fb6104ec3660046113cb565b611034565b3480156104fd57600080fd5b506101c361050c3660046113cb565b61106c565b34801561051d57600080fd5b506101c36110ba565b34801561053257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056557600080fd5b50610393610574366004611416565b6110ef565b34801561058557600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6003546000901561061757600380546105c890600190611467565b815481106105d8576105d861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60035460009061061b90600190611467565b600061063c6105ad565b8211156106f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546107ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6003546000905b8082101561084457600060026107c883856114ad565b6107d291906114c5565b905084600382815481106107e8576107e861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16101561083a576108338160016114ad565b925061083e565b8091505b506107b2565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f757470757473000060648201526084016106ed565b60035481106109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b7f0000000000000000000000000000000000000000000000000000000000000000600382815481106109fb576109fb61147e565b6000918252602090912060016002909202010154610a2b906fffffffffffffffffffffffffffffffff1642611467565b10610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6000610ae960035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b610c146110ba565b8314610cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016106ed565b42610cd28461106c565b10610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016106ed565b83610dec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016106ed565b8115610ea85781814014610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a4016106ed565b82610eb260035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610ee491815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610fd057610fd061147e565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361105c83610632565b81548110610fd057610fd061147e565b60007f00000000000000000000000000000000000000000000000000000000000000006001548361109d9190611467565b6110a79190611500565b6002546110b491906114ad565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006110e56105ad565b61061b91906114ad565b600054610100900460ff161580801561110f5750600054600160ff909116105b806111295750303b158015611129575060005460ff166001145b6111b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ed565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561121357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156112ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b60028290556001839055801561133757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208083528351808285015260005b8181101561138557858101830151858201604001528201611369565b81811115611397576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113dd57600080fd5b5035919050565b600080600080608085870312156113fa57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561142957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561147957611479611438565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114c0576114c0611438565b500190565b6000826114fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561153857611538611438565b50029056fea164736f6c634300080f000a", + "deployedBytecode": "0x60806040526004361061018a5760003560e01c806393991af3116100d6578063cf8e5cf01161007f578063e1a41bcf11610059578063e1a41bcf14610526578063e4a3011614610559578063f4daa2911461057957600080fd5b8063cf8e5cf0146104d1578063d1de856c146104f1578063dcec33481461051157600080fd5b8063a8e4fb90116100b0578063a8e4fb9014610437578063bffa7f0f1461046a578063ce5db8d61461049e57600080fd5b806393991af3146103955780639aaab648146103c8578063a25ae557146103db57600080fd5b80636abcf563116101385780637f006420116101125780637f0064201461033d578063887862721461035d57806389c44cbb1461037357600080fd5b80636abcf563146102de5780636b4d98dd146102f357806370872aa51461032757600080fd5b8063534db0e211610169578063534db0e21461021f57806354fd4d501461027357806369f16eec146102c957600080fd5b80622134cc1461018f5780634599c788146101d6578063529933df146101eb575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101c36105ad565b3480156101f757600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561022b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611358565b3480156102d557600080fd5b506101c3610620565b3480156102ea57600080fd5b506003546101c3565b3480156102ff57600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033357600080fd5b506101c360015481565b34801561034957600080fd5b506101c36103583660046113cb565b610632565b34801561036957600080fd5b506101c360025481565b34801561037f57600080fd5b5061039361038e3660046113cb565b61084b565b005b3480156103a157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6103936103d63660046113e4565b610b21565b3480156103e757600080fd5b506103fb6103f63660046113cb565b610fa0565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561044357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b34801561047657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104aa57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104dd57600080fd5b506103fb6104ec3660046113cb565b611034565b3480156104fd57600080fd5b506101c361050c3660046113cb565b61106c565b34801561051d57600080fd5b506101c36110ba565b34801561053257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056557600080fd5b50610393610574366004611416565b6110ef565b34801561058557600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6003546000901561061757600380546105c890600190611467565b815481106105d8576105d861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60035460009061061b90600190611467565b600061063c6105ad565b8211156106f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546107ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6003546000905b8082101561084457600060026107c883856114ad565b6107d291906114c5565b905084600382815481106107e8576107e861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16101561083a576108338160016114ad565b925061083e565b8091505b506107b2565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f757470757473000060648201526084016106ed565b60035481106109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b7f0000000000000000000000000000000000000000000000000000000000000000600382815481106109fb576109fb61147e565b6000918252602090912060016002909202010154610a2b906fffffffffffffffffffffffffffffffff1642611467565b10610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6000610ae960035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b610c146110ba565b8314610cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016106ed565b42610cd28461106c565b10610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016106ed565b83610dec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016106ed565b8115610ea85781814014610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a4016106ed565b82610eb260035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610ee491815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610fd057610fd061147e565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361105c83610632565b81548110610fd057610fd061147e565b60007f00000000000000000000000000000000000000000000000000000000000000006001548361109d9190611467565b6110a79190611500565b6002546110b491906114ad565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006110e56105ad565b61061b91906114ad565b600054610100900460ff161580801561110f5750600054600160ff909116105b806111295750303b158015611129575060005460ff166001145b6111b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ed565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561121357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156112ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b60028290556001839055801561133757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208083528351808285015260005b8181101561138557858101830151858201604001528201611369565b81811115611397576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113dd57600080fd5b5035919050565b600080600080608085870312156113fa57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561142957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561147957611479611438565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114c0576114c0611438565b500190565b6000826114fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561153857611538611438565b50029056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "computeL2Timestamp(uint256)": { + "params": { + "_l2BlockNumber": "The L2 block number of the target block." + }, + "returns": { + "_0": "L2 timestamp of the given block." + } + }, + "constructor": { + "params": { + "_challenger": "The address of the challenger.", + "_l2BlockTime": "The time per L2 block, in seconds.", + "_proposer": "The address of the proposer.", + "_startingBlockNumber": "The number of the first L2 block.", + "_startingTimestamp": "The timestamp of the first L2 block.", + "_submissionInterval": "Interval in blocks at which checkpoints must be submitted." + } + }, + "deleteL2Outputs(uint256)": { + "params": { + "_l2OutputIndex": "Index of the first L2 output to be deleted. All outputs after this output will also be deleted." + } + }, + "getL2Output(uint256)": { + "params": { + "_l2OutputIndex": "Index of the output to return." + }, + "returns": { + "_0": "The output at the given index." + } + }, + "getL2OutputAfter(uint256)": { + "params": { + "_l2BlockNumber": "L2 block number to find a checkpoint for." + }, + "returns": { + "_0": "First checkpoint that commits to the given L2 block number." + } + }, + "getL2OutputIndexAfter(uint256)": { + "params": { + "_l2BlockNumber": "L2 block number to find a checkpoint for." + }, + "returns": { + "_0": "Index of the first checkpoint that commits to the given L2 block number." + } + }, + "initialize(uint256,uint256)": { + "params": { + "_startingBlockNumber": "Block number for the first recoded L2 block.", + "_startingTimestamp": "Timestamp for the first recoded L2 block." + } + }, + "latestBlockNumber()": { + "returns": { + "_0": "Latest submitted L2 block number." + } + }, + "latestOutputIndex()": { + "returns": { + "_0": "The number of outputs that have been proposed." + } + }, + "nextBlockNumber()": { + "returns": { + "_0": "Next L2 block number." + } + }, + "nextOutputIndex()": { + "returns": { + "_0": "The index of the next output to be proposed." + } + }, + "proposeL2Output(bytes32,uint256,bytes32,uint256)": { + "params": { + "_l1BlockHash": "A block hash which must be included in the current chain.", + "_l1BlockNumber": "The block number with the specified block hash.", + "_l2BlockNumber": "The L2 block number that resulted in _outputRoot.", + "_outputRoot": "The L2 output of the checkpoint block." + } + } + }, + "events": { + "OutputProposed(bytes32,uint256,uint256,uint256)": { + "params": { + "l1Timestamp": "The L1 timestamp when proposed.", + "l2BlockNumber": "The L2 block number of the output root.", + "l2OutputIndex": "The index of the output in the l2Outputs array.", + "outputRoot": "The output root." + } + }, + "OutputsDeleted(uint256,uint256)": { + "params": { + "newNextOutputIndex": "Next L2 output index after the deletion.", + "prevNextOutputIndex": "Next L2 output index before the deletion." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2OutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OutputProposed\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prevNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"newNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OutputsDeleted\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"CHALLENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PROPOSER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"deleteL2Outputs\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizationPeriodSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputAfter\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputIndexAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1BlockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"proposeL2Output\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"computeL2Timestamp(uint256)\":{\"params\":{\"_l2BlockNumber\":\"The L2 block number of the target block.\"},\"returns\":{\"_0\":\"L2 timestamp of the given block.\"}},\"constructor\":{\"params\":{\"_challenger\":\"The address of the challenger.\",\"_l2BlockTime\":\"The time per L2 block, in seconds.\",\"_proposer\":\"The address of the proposer.\",\"_startingBlockNumber\":\"The number of the first L2 block.\",\"_startingTimestamp\":\"The timestamp of the first L2 block.\",\"_submissionInterval\":\"Interval in blocks at which checkpoints must be submitted.\"}},\"deleteL2Outputs(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the first L2 output to be deleted. All outputs after this output will also be deleted.\"}},\"getL2Output(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the output to return.\"},\"returns\":{\"_0\":\"The output at the given index.\"}},\"getL2OutputAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"First checkpoint that commits to the given L2 block number.\"}},\"getL2OutputIndexAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"Index of the first checkpoint that commits to the given L2 block number.\"}},\"initialize(uint256,uint256)\":{\"params\":{\"_startingBlockNumber\":\"Block number for the first recoded L2 block.\",\"_startingTimestamp\":\"Timestamp for the first recoded L2 block.\"}},\"latestBlockNumber()\":{\"returns\":{\"_0\":\"Latest submitted L2 block number.\"}},\"latestOutputIndex()\":{\"returns\":{\"_0\":\"The number of outputs that have been proposed.\"}},\"nextBlockNumber()\":{\"returns\":{\"_0\":\"Next L2 block number.\"}},\"nextOutputIndex()\":{\"returns\":{\"_0\":\"The index of the next output to be proposed.\"}},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"params\":{\"_l1BlockHash\":\"A block hash which must be included in the current chain.\",\"_l1BlockNumber\":\"The block number with the specified block hash.\",\"_l2BlockNumber\":\"The L2 block number that resulted in _outputRoot.\",\"_outputRoot\":\"The L2 output of the checkpoint block.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CHALLENGER()\":{\"notice\":\"The address of the challenger. Can be updated via upgrade. This will be removed in the future, use `challenger` instead.\"},\"FINALIZATION_PERIOD_SECONDS()\":{\"notice\":\"The minimum time (in seconds) that must elapse before a withdrawal can be finalized.\"},\"L2_BLOCK_TIME()\":{\"notice\":\"The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\"},\"PROPOSER()\":{\"notice\":\"The address of the proposer. Can be updated via upgrade. This will be removed in the future, use `proposer` instead.\"},\"SUBMISSION_INTERVAL()\":{\"notice\":\"The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead.\"},\"challenger()\":{\"notice\":\"Getter for the challenger address.\"},\"computeL2Timestamp(uint256)\":{\"notice\":\"Returns the L2 timestamp corresponding to a given L2 block number.\"},\"constructor\":{\"notice\":\"Constructs the L2OutputOracle contract.\"},\"deleteL2Outputs(uint256)\":{\"notice\":\"Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs.\"},\"finalizationPeriodSeconds()\":{\"notice\":\"Getter for the FINALIZATION_PERIOD_SECONDS.\"},\"getL2Output(uint256)\":{\"notice\":\"Returns an output by index. Needed to return a struct instead of a tuple.\"},\"getL2OutputAfter(uint256)\":{\"notice\":\"Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"getL2OutputIndexAfter(uint256)\":{\"notice\":\"Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"initialize(uint256,uint256)\":{\"notice\":\"Initializer.\"},\"l2BlockTime()\":{\"notice\":\"Getter for the L2_BLOCK_TIME.\"},\"latestBlockNumber()\":{\"notice\":\"Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number.\"},\"latestOutputIndex()\":{\"notice\":\"Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet.\"},\"nextBlockNumber()\":{\"notice\":\"Computes the block number of the next L2 block that needs to be checkpointed.\"},\"nextOutputIndex()\":{\"notice\":\"Returns the index of the next output to be proposed.\"},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"notice\":\"Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer.\"},\"proposer()\":{\"notice\":\"Getter for the PROPOSER address.\"},\"startingBlockNumber()\":{\"notice\":\"The number of the first L2 block recorded in this contract.\"},\"startingTimestamp()\":{\"notice\":\"The timestamp of the first L2 block recorded in this contract.\"},\"submissionInterval()\":{\"notice\":\"Getter for the SUBMISSION_INTERVAL.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L2OutputOracle.sol\":\"L2OutputOracle\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47332, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 47335, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 76505, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "startingBlockNumber", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 76508, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "startingTimestamp", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 76513, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "l2Outputs", + "offset": 0, + "slot": "3", + "type": "t_array(t_struct(OutputProposal)90918_storage)dyn_storage" + } + ], + "types": { + "t_array(t_struct(OutputProposal)90918_storage)dyn_storage": { + "encoding": "dynamic_array", + "label": "struct Types.OutputProposal[]", + "numberOfBytes": "32", + "base": "t_struct(OutputProposal)90918_storage" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_struct(OutputProposal)90918_storage": { + "encoding": "inplace", + "label": "struct Types.OutputProposal", + "numberOfBytes": "64", + "members": [ + { + "astId": 90913, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "outputRoot", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 90915, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "timestamp", + "offset": 0, + "slot": "1", + "type": "t_uint128" + }, + { + "astId": 90917, + "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", + "label": "l2BlockNumber", + "offset": 16, + "slot": "1", + "type": "t_uint128" + } + ] + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x7b343318a5fc4bdc106bf119b1b9d28607d0229b1cd900e7dd0963283bc89fd5", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "CHALLENGER()": { + "notice": "The address of the challenger. Can be updated via upgrade. This will be removed in the future, use `challenger` instead." + }, + "FINALIZATION_PERIOD_SECONDS()": { + "notice": "The minimum time (in seconds) that must elapse before a withdrawal can be finalized." + }, + "L2_BLOCK_TIME()": { + "notice": "The time between L2 blocks in seconds. Once set, this value MUST NOT be modified." + }, + "PROPOSER()": { + "notice": "The address of the proposer. Can be updated via upgrade. This will be removed in the future, use `proposer` instead." + }, + "SUBMISSION_INTERVAL()": { + "notice": "The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead." + }, + "challenger()": { + "notice": "Getter for the challenger address." + }, + "computeL2Timestamp(uint256)": { + "notice": "Returns the L2 timestamp corresponding to a given L2 block number." + }, + "constructor": { + "notice": "Constructs the L2OutputOracle contract." + }, + "deleteL2Outputs(uint256)": { + "notice": "Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs." + }, + "finalizationPeriodSeconds()": { + "notice": "Getter for the FINALIZATION_PERIOD_SECONDS." + }, + "getL2Output(uint256)": { + "notice": "Returns an output by index. Needed to return a struct instead of a tuple." + }, + "getL2OutputAfter(uint256)": { + "notice": "Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." + }, + "getL2OutputIndexAfter(uint256)": { + "notice": "Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." + }, + "initialize(uint256,uint256)": { + "notice": "Initializer." + }, + "l2BlockTime()": { + "notice": "Getter for the L2_BLOCK_TIME." + }, + "latestBlockNumber()": { + "notice": "Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number." + }, + "latestOutputIndex()": { + "notice": "Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet." + }, + "nextBlockNumber()": { + "notice": "Computes the block number of the next L2 block that needs to be checkpointed." + }, + "nextOutputIndex()": { + "notice": "Returns the index of the next output to be proposed." + }, + "proposeL2Output(bytes32,uint256,bytes32,uint256)": { + "notice": "Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer." + }, + "proposer()": { + "notice": "Getter for the PROPOSER address." + }, + "startingBlockNumber()": { + "notice": "The number of the first L2 block recorded in this contract." + }, + "startingTimestamp()": { + "notice": "The timestamp of the first L2 block recorded in this contract." + }, + "submissionInterval()": { + "notice": "Getter for the SUBMISSION_INTERVAL." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "OutputProposed(bytes32,uint256,uint256,uint256)": { + "notice": "Emitted when an output is proposed." + }, + "OutputsDeleted(uint256,uint256)": { + "notice": "Emitted when outputs are deleted." + } + }, + "notice": "The L2OutputOracle contains an array of L2 state outputs, where each output is a commitment to the state of the L2 chain. Other contracts like the OptimismPortal use these outputs to verify information about the state of L2." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/L2OutputOracleProxy.json b/e2e/deployments/devnetL1/L2OutputOracleProxy.json new file mode 100644 index 000000000000..d8921f56f41c --- /dev/null +++ b/e2e/deployments/devnetL1/L2OutputOracleProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0xD3292428DE99a781A4A5e503622E8c80E5383e20", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xe2c655190a0d37a6359cad6b9b5e611370c13a71f9c1318502bca476191104a7", + "transactionIndex": "0xe", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x9ac7ed", + "gasUsed": "0x80250", + "contractAddress": "0xD3292428DE99a781A4A5e503622E8c80E5383e20", + "logs": [ + { + "address": "0xD3292428DE99a781A4A5e503622E8c80E5383e20", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0xe2c655190a0d37a6359cad6b9b5e611370c13a71f9c1318502bca476191104a7", + "transactionIndex": "0xe", + "logIndex": "0x1b", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000040000000000000000000800000000000000000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0xe2c655190a0d37a6359cad6b9b5e611370c13a71f9c1318502bca476191104a7", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/Mips.json b/e2e/deployments/devnetL1/Mips.json new file mode 100644 index 000000000000..42b56fd1edc6 --- /dev/null +++ b/e2e/deployments/devnetL1/Mips.json @@ -0,0 +1,126 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_oracle", + "type": "address", + "internalType": "contract IPreimageOracle" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "BRK_START", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint32", + "internalType": "uint32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "oracle", + "inputs": [], + "outputs": [ + { + "name": "oracle_", + "type": "address", + "internalType": "contract IPreimageOracle" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "step", + "inputs": [ + { + "name": "_stateData", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_proof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_localContext", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "nonpayable" + } + ], + "address": "0xfA03f595c27DD29befE52727eA12AE3620cEE277", + "args": [ + "0xb018cA14112C15D21d0FB22568fe4475A58EDFc0" + ], + "bytecode": "0x60a060405234801561001057600080fd5b50604051611ec2380380611ec283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611e3161009160003960008181608501526115ef0152611e316000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "details": "https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdfhttps://www.cs.cmu.edu/afs/cs/academic/class/15740-f97/public/doc/mips-isa.pdf (page A-177)https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdfhttps://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formatshttps://github.com/golang/go/blob/master/src/syscall/zerrors_linux_mips.go MIPS linux kernel errors used by Go runtime", + "methods": { + "constructor": { + "params": { + "_oracle": "The address of the preimage oracle contract." + } + }, + "oracle()": { + "returns": { + "oracle_": "The IPreimageOracle contract." + } + }, + "step(bytes,bytes,bytes32)": { + "params": { + "_localContext": "The local key context for the preimage oracle. Optional, can be set as a constant if the caller only requires one set of local keys.", + "_proof": "The encoded proof data for leaves within the MIPS VM's memory.", + "_stateData": "The encoded state witness data." + } + } + }, + "title": "MIPS" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPreimageOracle\",\"name\":\"_oracle\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BRK_START\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IPreimageOracle\",\"name\":\"oracle_\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_proof\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"_localContext\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"step\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_oracle\":\"The address of the preimage oracle contract.\"}},\"oracle()\":{\"returns\":{\"oracle_\":\"The IPreimageOracle contract.\"}},\"step(bytes,bytes,bytes32)\":{\"params\":{\"_localContext\":\"The local key context for the preimage oracle. Optional, can be set as a constant if the caller only requires one set of local keys.\",\"_proof\":\"The encoded proof data for leaves within the MIPS VM's memory.\",\"_stateData\":\"The encoded state witness data.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BRK_START()\":{\"notice\":\"Start of the data segment.\"},\"oracle()\":{\"notice\":\"Getter for the pre-image oracle contract.\"},\"step(bytes,bytes,bytes32)\":{\"notice\":\"Executes a single step of the vm. Will revert if any required input state is missing.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/cannon/MIPS.sol\":\"MIPS\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"src/cannon/MIPS.sol\":{\"keccak256\":\"0xfac3a4db59f8a69474c1438208529683e49da51d3e8b840ddc8793cccb4e9788\",\"urls\":[\"bzz-raw://762a10a91d30ce171391efcbd7648e47be06b4a2b632778ed90b754c3ca09142\",\"dweb:/ipfs/QmdsW789ToA5A39ZDqyV1C8yR5Pqs8oXJ8DfuM9uuNYbnA\"],\"license\":\"MIT\"},\"src/cannon/PreimageKeyLib.sol\":{\"keccak256\":\"0x082e910b8a3f523ac0920f0bc5a09e127fe9e48127694e5a0efce820d4654e85\",\"urls\":[\"bzz-raw://bce8c13880b75f2d8561188279b2333c455c831216fc29375570d9c93767c6cc\",\"dweb:/ipfs/QmRmworxD49TBLcLS81sNUEfkQVgg3tf2L6pUDCduDJvWm\"],\"license\":\"MIT\"},\"src/cannon/interfaces/IPreimageOracle.sol\":{\"keccak256\":\"0xbba7c884cae96e8891ffa27de01049cc763665a8c009f7bb09572a56009cebe0\",\"urls\":[\"bzz-raw://dcda03b5007b6f0053e721fbbd9850ead181ea7366bc826294bfe1fb812c8e7c\",\"dweb:/ipfs/QmUKTfc13UnzMgKoghCmCdYHc35y1tRLBADFWgxibPbSxX\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x9c140ba03060383223f63d347591befe7843545ff034dfdb19c2edafb2267b40", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "BRK_START()": { + "notice": "Start of the data segment." + }, + "oracle()": { + "notice": "Getter for the pre-image oracle contract." + }, + "step(bytes,bytes,bytes32)": { + "notice": "Executes a single step of the vm. Will revert if any required input state is missing." + } + }, + "notice": "The MIPS contract emulates a single MIPS instruction. Note that delay slots are isolated instructions: the nextPC in the state pre-schedules where the VM jumps next. The Step input is a packed VM state, with binary-merkle-tree witness data for memory reads/writes. The Step outputs a keccak256 hash of the packed VM State, and logs the resulting state for offchain usage." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/OptimismMintableERC20Factory.json b/e2e/deployments/devnetL1/OptimismMintableERC20Factory.json new file mode 100644 index 000000000000..be2b8bd4efd8 --- /dev/null +++ b/e2e/deployments/devnetL1/OptimismMintableERC20Factory.json @@ -0,0 +1,290 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_bridge", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "BRIDGE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bridge", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "createOptimismMintableERC20", + "inputs": [ + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_symbol", + "type": "string", + "internalType": "string" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "createOptimismMintableERC20WithDecimals", + "inputs": [ + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_symbol", + "type": "string", + "internalType": "string" + }, + { + "name": "_decimals", + "type": "uint8", + "internalType": "uint8" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "createStandardL2Token", + "inputs": [ + { + "name": "_remoteToken", + "type": "address", + "internalType": "address" + }, + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_symbol", + "type": "string", + "internalType": "string" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "OptimismMintableERC20Created", + "inputs": [ + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "deployer", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "StandardL2TokenCreated", + "inputs": [ + { + "name": "remoteToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "localToken", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x3fDDA84fBbC657b3D26d614f0Fe2147f1Ca13C08", + "args": [ + "0xe50ea86676B29448a4e586511d8920105cEd1159" + ], + "bytecode": "0x60a060405234801561001057600080fd5b50604051611f59380380611f5983398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ec0610099600039600081816101420152818161016d01526102880152611ec06000f3fe60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f1462000129578063e78cea921462000140578063ee9a31a2146200016757600080fd5b806354fd4d501462000080578063896f93d114620000d55780638cf0629c1462000112575b600080fd5b620000bd6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b604051620000cc91906200042e565b60405180910390f35b620000ec620000e636600462000556565b6200018f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000cc565b620000ec62000123366004620005d3565b620001a6565b620000ec6200013a36600462000556565b620003a1565b7f0000000000000000000000000000000000000000000000000000000000000000620000ec565b620000ec7f000000000000000000000000000000000000000000000000000000000000000081565b60006200019e848484620003a1565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b6000858585856040516020016200026b94939291906200066a565b6040516020818303038152906040528051906020012090506000817f000000000000000000000000000000000000000000000000000000000000000088888888604051620002b990620003b2565b620002c9959493929190620006c4565b8190604051809103906000f5905080158015620002ea573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b60006200019e8484846012620001a6565b61178a806200072a83390190565b6000815180845260005b81811015620003e857602081850181015186830182015201620003ca565b81811115620003fb576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620004436020830184620003c0565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200046f57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620004b557600080fd5b813567ffffffffffffffff80821115620004d357620004d362000474565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200051c576200051c62000474565b816040528381528660208588010111156200053657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200056c57600080fd5b62000577846200044a565b9250602084013567ffffffffffffffff808211156200059557600080fd5b620005a387838801620004a3565b93506040860135915080821115620005ba57600080fd5b50620005c986828701620004a3565b9150509250925092565b60008060008060808587031215620005ea57600080fd5b620005f5856200044a565b9350602085013567ffffffffffffffff808211156200061357600080fd5b6200062188838901620004a3565b945060408701359150808211156200063857600080fd5b506200064787828801620004a3565b925050606085013560ff811681146200065f57600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200069b6080830186620003c0565b8281036040840152620006af8186620003c0565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620006ff60a0830186620003c0565b8281036060840152620007138186620003c0565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f1462000129578063e78cea921462000140578063ee9a31a2146200016757600080fd5b806354fd4d501462000080578063896f93d114620000d55780638cf0629c1462000112575b600080fd5b620000bd6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b604051620000cc91906200042e565b60405180910390f35b620000ec620000e636600462000556565b6200018f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000cc565b620000ec62000123366004620005d3565b620001a6565b620000ec6200013a36600462000556565b620003a1565b7f0000000000000000000000000000000000000000000000000000000000000000620000ec565b620000ec7f000000000000000000000000000000000000000000000000000000000000000081565b60006200019e848484620003a1565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b6000858585856040516020016200026b94939291906200066a565b6040516020818303038152906040528051906020012090506000817f000000000000000000000000000000000000000000000000000000000000000088888888604051620002b990620003b2565b620002c9959493929190620006c4565b8190604051809103906000f5905080158015620002ea573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b60006200019e8484846012620001a6565b61178a806200072a83390190565b6000815180845260005b81811015620003e857602081850181015186830182015201620003ca565b81811115620003fb576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620004436020830184620003c0565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200046f57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620004b557600080fd5b813567ffffffffffffffff80821115620004d357620004d362000474565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200051c576200051c62000474565b816040528381528660208588010111156200053657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200056c57600080fd5b62000577846200044a565b9250602084013567ffffffffffffffff808211156200059557600080fd5b620005a387838801620004a3565b93506040860135915080821115620005ba57600080fd5b50620005c986828701620004a3565b9150509250925092565b60008060008060808587031215620005ea57600080fd5b620005f5856200044a565b9350602085013567ffffffffffffffff808211156200061357600080fd5b6200062188838901620004a3565b945060408701359150808211156200063857600080fd5b506200064787828801620004a3565b925050606085013560ff811681146200065f57600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200069b6080830186620003c0565b8281036040840152620006af8186620003c0565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620006ff60a0830186620003c0565b8281036060840152620007138186620003c0565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_bridge": "Address of the StandardBridge on this chain." + } + }, + "createOptimismMintableERC20(address,string,string)": { + "params": { + "_name": "ERC20 name.", + "_remoteToken": "Address of the token on the remote chain.", + "_symbol": "ERC20 symbol." + }, + "returns": { + "_0": "Address of the newly created token." + } + }, + "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { + "params": { + "_decimals": "ERC20 decimals", + "_name": "ERC20 name.", + "_remoteToken": "Address of the token on the remote chain.", + "_symbol": "ERC20 symbol." + }, + "returns": { + "_0": "Address of the newly created token." + } + }, + "createStandardL2Token(address,string,string)": { + "params": { + "_name": "ERC20 name.", + "_remoteToken": "Address of the token on the remote chain.", + "_symbol": "ERC20 symbol." + }, + "returns": { + "_0": "Address of the newly created token." + } + } + }, + "events": { + "OptimismMintableERC20Created(address,address,address)": { + "params": { + "deployer": "Address of the account that deployed the token.", + "localToken": "Address of the created token on the local chain.", + "remoteToken": "Address of the corresponding token on the remote chain." + } + }, + "StandardL2TokenCreated(address,address)": { + "params": { + "localToken": "Address of the created token on the local chain.", + "remoteToken": "Address of the token on the remote chain." + } + } + }, + "title": "OptimismMintableERC20Factory" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OptimismMintableERC20Created\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"StandardL2TokenCreated\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_bridge\":\"Address of the StandardBridge on this chain.\"}},\"createOptimismMintableERC20(address,string,string)\":{\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"params\":{\"_decimals\":\"ERC20 decimals\",\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createStandardL2Token(address,string,string)\":{\"custom:legacy\":\"@notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the newer createOptimismMintableERC20 function, which has a more intuitive name.\",\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BRIDGE()\":{\"notice\":\"Address of the StandardBridge on this chain.\"},\"bridge()\":{\"notice\":\"Getter function for the address of the StandardBridge on this chain.Address of the StandardBridge on this chain.\"},\"createOptimismMintableERC20(address,string,string)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract.\"},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract, with specified decimals.\"},\"version()\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/OptimismMintableERC20Factory.sol\":\"OptimismMintableERC20Factory\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0x76feb3c6ccd232d19ca58cf06e4c28db97bcf07d8292889b71222e02f84041bb\",\"urls\":[\"bzz-raw://2111dbb54ab5d78efbc07dfb980b50ee2d128d10cc2076b0d27295ee65308d60\",\"dweb:/ipfs/QmRoHCbxb1yCx6ok8ggK1TExq1XbJucrB3GAGxvjmVkC7X\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0xbbc8e371f246ce0a4dbdc16fd5790848de4adcdd883264a9fd2157961c77237e", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "BRIDGE()": { + "notice": "Address of the StandardBridge on this chain." + }, + "bridge()": { + "notice": "Getter function for the address of the StandardBridge on this chain.Address of the StandardBridge on this chain." + }, + "createOptimismMintableERC20(address,string,string)": { + "notice": "Creates an instance of the OptimismMintableERC20 contract." + }, + "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { + "notice": "Creates an instance of the OptimismMintableERC20 contract, with specified decimals." + }, + "version()": { + "notice": "The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.Semantic version." + } + }, + "events": { + "OptimismMintableERC20Created(address,address,address)": { + "notice": "Emitted whenever a new OptimismMintableERC20 is created." + } + }, + "notice": "OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 contracts on the network it's deployed to. Simplifies the deployment process for users who may be less familiar with deploying smart contracts. Designed to be backwards compatible with the older StandardL2ERC20Factory contract." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/OptimismMintableERC20FactoryProxy.json b/e2e/deployments/devnetL1/OptimismMintableERC20FactoryProxy.json new file mode 100644 index 000000000000..72c1fc59f78e --- /dev/null +++ b/e2e/deployments/devnetL1/OptimismMintableERC20FactoryProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x2a16b5Df4D7c73111d66EE83Bde89E8366fC89Fc", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xa6e786886a5aaf10c157d805f5e76e4c407ad89550d9f56c6ef4d2c90f678af1", + "transactionIndex": "0x1", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0xc50ae", + "gasUsed": "0x80250", + "contractAddress": "0x2a16b5Df4D7c73111d66EE83Bde89E8366fC89Fc", + "logs": [ + { + "address": "0x2a16b5Df4D7c73111d66EE83Bde89E8366fC89Fc", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x7fe2a0299894506e1cefebea041113eee39ce0f4ea67ef0fd12a070539025bc4", + "blockNumber": "0xa", + "transactionHash": "0xa6e786886a5aaf10c157d805f5e76e4c407ad89550d9f56c6ef4d2c90f678af1", + "transactionIndex": "0x1", + "logIndex": "0x0", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000040000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc6ef3dc7" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0xa6e786886a5aaf10c157d805f5e76e4c407ad89550d9f56c6ef4d2c90f678af1", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/OptimismPortal.json b/e2e/deployments/devnetL1/OptimismPortal.json new file mode 100644 index 000000000000..0c07eb3c4d9d --- /dev/null +++ b/e2e/deployments/devnetL1/OptimismPortal.json @@ -0,0 +1,946 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_l2Oracle", + "type": "address", + "internalType": "contract L2OutputOracle" + }, + { + "name": "_systemConfig", + "type": "address", + "internalType": "contract SystemConfig" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "GUARDIAN", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "L2_ORACLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract L2OutputOracle" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "SYSTEM_CONFIG", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SystemConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "depositTransaction", + "inputs": [ + { + "name": "_to", + "type": "address", + "internalType": "address" + }, + { + "name": "_value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_gasLimit", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "_isCreation", + "type": "bool", + "internalType": "bool" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "donateETH", + "inputs": [], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "finalizeWithdrawalTransaction", + "inputs": [ + { + "name": "_tx", + "type": "tuple", + "internalType": "struct Types.WithdrawalTransaction", + "components": [ + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "sender", + "type": "address", + "internalType": "address" + }, + { + "name": "target", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasLimit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "finalizedWithdrawals", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "guardian", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_superchainConfig", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "isOutputFinalized", + "inputs": [ + { + "name": "_l2OutputIndex", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "l2Oracle", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract L2OutputOracle" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "l2Sender", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "minimumGasLimit", + "inputs": [ + { + "name": "_byteCount", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "params", + "inputs": [], + "outputs": [ + { + "name": "prevBaseFee", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "prevBoughtGas", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "prevBlockNum", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "paused_", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proveWithdrawalTransaction", + "inputs": [ + { + "name": "_tx", + "type": "tuple", + "internalType": "struct Types.WithdrawalTransaction", + "components": [ + { + "name": "nonce", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "sender", + "type": "address", + "internalType": "address" + }, + { + "name": "target", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasLimit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "_l2OutputIndex", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_outputRootProof", + "type": "tuple", + "internalType": "struct Types.OutputRootProof", + "components": [ + { + "name": "version", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "stateRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "messagePasserStorageRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "latestBlockhash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "_withdrawalProof", + "type": "bytes[]", + "internalType": "bytes[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "provenWithdrawals", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "outputRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "timestamp", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "l2OutputIndex", + "type": "uint128", + "internalType": "uint128" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "superchainConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SuperchainConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "systemConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract SystemConfig" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TransactionDeposited", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "version", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "opaqueData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Unpaused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WithdrawalFinalized", + "inputs": [ + { + "name": "withdrawalHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "success", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WithdrawalProven", + "inputs": [ + { + "name": "withdrawalHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0xBbAc1710d0AeC5053ae07DC6B035dA675deBa34F", + "args": [ + "0xD3292428DE99a781A4A5e503622E8c80E5383e20", + "0x654fe8bC4F8Bf51f0CeC4567399aD7067E145C3F" + ], + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200570c3803806200570c83398101604081905262000034916200028f565b6001600160a01b03808316608052811660a0526200005360006200005b565b5050620002ce565b600054610100900460ff16158080156200007c5750600054600160ff909116105b80620000ac57506200009930620001c460201b62001bbd1760201c565b158015620000ac575060005460ff166001145b620001155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000139576000805461ff0019166101001790555b603280546001600160a01b03191661dead179055603580546001600160a01b03841661010002610100600160a81b031990911617905562000179620001d3565b8015620001c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002405760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200010c565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200028c57600080fd5b50565b60008060408385031215620002a357600080fd5b8251620002b08162000276565b6020840151909250620002c38162000276565b809150509250929050565b60805160a0516153d962000333600039600081816101fb0152818161059101526121ce0152600081816101a00152818161036501528181610a4601528181610c270152818161102c015281816112d2015281816115440152611fba01526153d96000f3fe6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b506101876102813660046149ca565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b20565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b33565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b4c565b6110c2565b34801561036257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b33565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614ba6565b61199f565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614bc1565b6119b8565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b33565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614bec565b6105b3565b34801561058b57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b610674835161199f565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614c69565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b20565b60405180910390a450506108458282611bd9565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614cce565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d0b565b519050610ae0610adb36869003860186614d70565b611f06565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f62565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d0b565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614dd6565b8a60400135611f92565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e5a565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d0b565b602001516fffffffffffffffffffffffffffffffff16611fb6565b92915050565b60006108e161084e565b6110ca610f4e565b15611131576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e582611f62565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135f9190614e77565b81602001516fffffffffffffffffffffffffffffffff16101561142a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144981602001516fffffffffffffffffffffffffffffffff16611fb6565b6114fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c49190614d0b565b825181519192501461167e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169d81602001516fffffffffffffffffffffffffffffffff16611fb6565b61174f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161189093929190612059565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f590841515815260200190565b60405180910390a28015801561190b5750326001145b15611998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ac826010614ebf565b6110b290615208614eef565b600054610100900460ff16158080156119d85750600054600160ff909116105b806119f25750303b1580156119f2575060005460ff166001145b611a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611adc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b566120b7565b8015611bb957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c0f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f1b565b90506000611c1b61219a565b90506000816020015160ff16826000015163ffffffff16611c3c9190614f61565b90508215611d7357600154600090611c73908390700100000000000000000000000000000000900467ffffffffffffffff16614fc9565b90506000836040015160ff1683611c8a919061503d565b600154611caa9084906fffffffffffffffffffffffffffffffff1661503d565b611cb49190614f61565b600154909150600090611d0590611cde9084906fffffffffffffffffffffffffffffffff166150f9565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661225b565b90506001861115611d3457611d31611cde82876040015160ff1660018a611d2c9190614f1b565b61227a565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611da6908490700100000000000000000000000000000000900467ffffffffffffffff16614eef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611eb5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661516d565b90506000611ec748633b9aca006122cf565b611ed190836151aa565b905060005a611ee09088614f1b565b905080821115611efc57611efc611ef78284614f1b565b6122e6565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f45949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f459790969591016151be565b600080611f9e86612314565b9050611fac81868686612346565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612023573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120479190614e77565b6120519083615215565b421192915050565b6000806000612069866000612376565b90508061209f576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff1661214e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615252565b600061227061226a8585612394565b836123a4565b90505b9392505050565b6000670de0b6b3a76400006122bb6122928583614f61565b6122a490670de0b6b3a7640000614fc9565b6122b685670de0b6b3a764000061503d565b6123b3565b6122c5908661503d565b6122709190614f61565b6000818310156122df5781612273565b5090919050565b6000805a90505b825a6122f99083614f1b565b101561230f57612308826152f1565b91506122ed565b505050565b6060818051906020012060405160200161233091815260200190565b6040516020818303038152906040529050919050565b600061236d846123578786866123e4565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156122df5781612273565b60008183126122df5781612273565b6000612273670de0b6b3a7640000836123cb86612e62565b6123d5919061503d565b6123df9190614f61565b6130a6565b60606000845111612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061245c846132e5565b90506000612469866133d1565b905060008460405160200161248091815260200190565b60405160208183030381529060405290506000805b8451811015612dd95760008582815181106124b2576124b2615329565b60200260200101519050845183111561254d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b82600003612606578051805160209182012060405161259b9261257592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61275d565b8051516020116126bc57805180516020918201206040516126309261257592910190815260200190565b612601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461275d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b61276960106001615215565b8160200151510361294557845183036128dd576127a3816020015160108151811061279657612796615329565b6020026020010151613434565b96506000875111612836576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128449190614f1b565b82146128d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b505050505050612273565b60008584815181106128f1576128f1615329565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061291c5761291c615329565b6020026020010151905061292f81613594565b955061293c600186615215565b94505050612dc6565b600281602001515103612d3e57600061295d826135b9565b905060008160008151811061297457612974615329565b016020015160f81c9050600061298b600283615358565b61299690600261537a565b905060006129a7848360ff166135dd565b905060006129b58a896135dd565b905060006129c38383613613565b905080835114612a55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612a6a575060ff85166003145b15612c595780825114612aff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b19876020015160018151811061279657612796615329565b9c5060008d5111612bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bba9190614f1b565b8814612c48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b505050505050505050505050612273565b60ff85161580612c6c575060ff85166001145b15612cab57612c988760200151600181518110612c8b57612c8b615329565b6020026020010151613594565b9950612ca4818a615215565b9850612d33565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612dc6565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612dd1816152f1565b915050612495565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612ecd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612eda846136c7565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130d757506000919050565b680755bf798b4a1bf1e58212613149576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff811115613303576133036147ea565b60405190808252806020026020018201604052801561334857816020015b60408051808201909152606080825260208201528152602001906001900390816133215790505b50915060005b818110156133ca57604051806040016040528085838151811061337357613373615329565b602002602001015181526020016133a286848151811061339557613395615329565b602002602001015161379d565b8152508382815181106133b7576133b7615329565b602090810291909101015260010161334e565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613429578060011b82018184015160001a8060041c8253600f8116600183015350506001016133fb565b509295945050505050565b60606000806000613444856137b0565b91945092509050600081600181111561345f5761345f61539d565b146134ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6134f68284615215565b855114613585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b61236d8560200151848461421d565b606060208260000151106135b0576135ab82613434565b6110b2565b6110b2826142b1565b60606110b26135d8836020015160008151811061279657612796615329565b6133d1565b6060825182106135fc57506040805160208101909152600081526110b2565b612273838384865161360e9190614f1b565b6142c7565b6000808251845110613626578251613629565b83515b90505b80821080156136b0575082828151811061364857613648615329565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684838151811061368757613687615329565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136c05781600101915061362c565b5092915050565b6000808211613732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137ab8361449f565b614588565b60008060008084600001511161386e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f8111613893576000600160009450945094505050614216565b60b78111613aa15760006138a8608083614f1b565b905080876000015111613963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806139dc57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613a8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614216915050565b60bf8111613def576000613ab660b783614f1b565b905080876000015111613b71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d1d8184615215565b895111613dd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613ddd836001615215565b97509550600094506142169350505050565b60f78111613ed0576000613e0460c083614f1b565b905080876000015111613ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614216915050565b6000613edd60f783614f1b565b905080876000015111613f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161413a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141448184615215565b8951116141f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614204836001615215565b97509550600194506142169350505050565b9193909250565b60608167ffffffffffffffff811115614238576142386147ea565b6040519080825280601f01601f191660200182016040528015614262576020820181803683370190505b50905081156122735760006142778486615215565b90506020820160005b84811015614298578281015182820152602001614280565b848111156142a7576000858301525b5050509392505050565b60606110b282602001516000846000015161421d565b60608182601f011015614336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8183018451101561440f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561442e5760405191506000825260208201604052614496565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561446757805183526020928301920161444f565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161456a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b60606000806000614598856137b0565b9194509250905060018160018111156145b3576145b361539d565b14614640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161464c8385615215565b146146d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816146f05790505093506000835b86518110156147de576000806147636040518060400160405280858c600001516147479190614f1b565b8152602001858c6020015161475c9190615215565b90526137b0565b50915091506040518060400160405280838361477f9190615215565b8152602001848b602001516147949190615215565b8152508885815181106147a9576147a9615329565b60209081029190910101526147bf600185615215565b93506147cb8183615215565b6147d59084615215565b9250505061471d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614860576148606147ea565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461488a57600080fd5b50565b600082601f83011261489e57600080fd5b813567ffffffffffffffff8111156148b8576148b86147ea565b6148e960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614819565b8181528460208386010111156148fe57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561492d57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614951576149516147ea565b81604052829350843583526020850135915061496c82614868565b8160208401526040850135915061498282614868565b816040840152606085013560608401526080850135608084015260a08501359150808211156149b057600080fd5b506149bd8582860161488d565b60a0830152505092915050565b600080600080600085870360e08112156149e357600080fd5b863567ffffffffffffffff808211156149fb57600080fd5b614a078a838b0161491b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a4057600080fd5b60408901955060c0890135925080831115614a5a57600080fd5b828901925089601f840112614a6e57600080fd5b8235915080821115614a7f57600080fd5b508860208260051b8401011115614a9557600080fd5b959894975092955050506020019190565b60005b83811015614ac1578181015183820152602001614aa9565b83811115614ad0576000848401525b50505050565b60008151808452614aee816020860160208601614aa6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122736020830184614ad6565b600060208284031215614b4557600080fd5b5035919050565b600060208284031215614b5e57600080fd5b813567ffffffffffffffff811115614b7557600080fd5b614b818482850161491b565b949350505050565b803567ffffffffffffffff81168114614ba157600080fd5b919050565b600060208284031215614bb857600080fd5b61227382614b89565b600060208284031215614bd357600080fd5b813561227381614868565b801515811461488a57600080fd5b600080600080600060a08688031215614c0457600080fd5b8535614c0f81614868565b945060208601359350614c2460408701614b89565b92506060860135614c3481614bde565b9150608086013567ffffffffffffffff811115614c5057600080fd5b614c5c8882890161488d565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cbd816049850160208701614aa6565b919091016049019695505050505050565b600060208284031215614ce057600080fd5b815161227381614868565b80516fffffffffffffffffffffffffffffffff81168114614ba157600080fd5b600060608284031215614d1d57600080fd5b6040516060810181811067ffffffffffffffff82111715614d4057614d406147ea565b60405282518152614d5360208401614ceb565b6020820152614d6460408401614ceb565b60408201529392505050565b600060808284031215614d8257600080fd5b6040516080810181811067ffffffffffffffff82111715614da557614da56147ea565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614df157614df16147ea565b8360051b6020614e02818301614819565b868152918501918181019036841115614e1a57600080fd5b865b84811015614e4e57803586811115614e345760008081fd5b614e4036828b0161488d565b845250918301918301614e1c565b50979650505050505050565b600060208284031215614e6c57600080fd5b815161227381614bde565b600060208284031215614e8957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614ee657614ee6614e90565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f1257614f12614e90565b01949350505050565b600082821015614f2d57614f2d614e90565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f7057614f70614f32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fc457614fc4614e90565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561500357615003614e90565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561503757615037614e90565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561507e5761507e614e90565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150b9576150b9614e90565b600087129250878205871284841616156150d5576150d5614e90565b878505871281841616156150eb576150eb614e90565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561513357615133614e90565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561516757615167614e90565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151a5576151a5614e90565b500290565b6000826151b9576151b9614f32565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261520960c0830184614ad6565b98975050505050505050565b6000821982111561522857615228614e90565b500190565b805163ffffffff81168114614ba157600080fd5b805160ff81168114614ba157600080fd5b600060c0828403121561526457600080fd5b60405160c0810181811067ffffffffffffffff82111715615287576152876147ea565b6040526152938361522d565b81526152a160208401615241565b60208201526152b260408401615241565b60408201526152c36060840161522d565b60608201526152d46080840161522d565b60808201526152e560a08401614ceb565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361532257615322614e90565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061536b5761536b614f32565b8060ff84160691505092915050565b600060ff821660ff84168082101561539457615394614e90565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b506101876102813660046149ca565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b20565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b33565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b4c565b6110c2565b34801561036257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b33565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614ba6565b61199f565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614bc1565b6119b8565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b33565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614bec565b6105b3565b34801561058b57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b610674835161199f565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614c69565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b20565b60405180910390a450506108458282611bd9565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614cce565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d0b565b519050610ae0610adb36869003860186614d70565b611f06565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f62565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d0b565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614dd6565b8a60400135611f92565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e5a565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d0b565b602001516fffffffffffffffffffffffffffffffff16611fb6565b92915050565b60006108e161084e565b6110ca610f4e565b15611131576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e582611f62565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135f9190614e77565b81602001516fffffffffffffffffffffffffffffffff16101561142a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144981602001516fffffffffffffffffffffffffffffffff16611fb6565b6114fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c49190614d0b565b825181519192501461167e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169d81602001516fffffffffffffffffffffffffffffffff16611fb6565b61174f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161189093929190612059565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f590841515815260200190565b60405180910390a28015801561190b5750326001145b15611998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ac826010614ebf565b6110b290615208614eef565b600054610100900460ff16158080156119d85750600054600160ff909116105b806119f25750303b1580156119f2575060005460ff166001145b611a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611adc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b566120b7565b8015611bb957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c0f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f1b565b90506000611c1b61219a565b90506000816020015160ff16826000015163ffffffff16611c3c9190614f61565b90508215611d7357600154600090611c73908390700100000000000000000000000000000000900467ffffffffffffffff16614fc9565b90506000836040015160ff1683611c8a919061503d565b600154611caa9084906fffffffffffffffffffffffffffffffff1661503d565b611cb49190614f61565b600154909150600090611d0590611cde9084906fffffffffffffffffffffffffffffffff166150f9565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661225b565b90506001861115611d3457611d31611cde82876040015160ff1660018a611d2c9190614f1b565b61227a565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611da6908490700100000000000000000000000000000000900467ffffffffffffffff16614eef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611eb5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661516d565b90506000611ec748633b9aca006122cf565b611ed190836151aa565b905060005a611ee09088614f1b565b905080821115611efc57611efc611ef78284614f1b565b6122e6565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f45949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f459790969591016151be565b600080611f9e86612314565b9050611fac81868686612346565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612023573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120479190614e77565b6120519083615215565b421192915050565b6000806000612069866000612376565b90508061209f576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff1661214e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615252565b600061227061226a8585612394565b836123a4565b90505b9392505050565b6000670de0b6b3a76400006122bb6122928583614f61565b6122a490670de0b6b3a7640000614fc9565b6122b685670de0b6b3a764000061503d565b6123b3565b6122c5908661503d565b6122709190614f61565b6000818310156122df5781612273565b5090919050565b6000805a90505b825a6122f99083614f1b565b101561230f57612308826152f1565b91506122ed565b505050565b6060818051906020012060405160200161233091815260200190565b6040516020818303038152906040529050919050565b600061236d846123578786866123e4565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156122df5781612273565b60008183126122df5781612273565b6000612273670de0b6b3a7640000836123cb86612e62565b6123d5919061503d565b6123df9190614f61565b6130a6565b60606000845111612451576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061245c846132e5565b90506000612469866133d1565b905060008460405160200161248091815260200190565b60405160208183030381529060405290506000805b8451811015612dd95760008582815181106124b2576124b2615329565b60200260200101519050845183111561254d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b82600003612606578051805160209182012060405161259b9261257592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61275d565b8051516020116126bc57805180516020918201206040516126309261257592910190815260200190565b612601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461275d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b61276960106001615215565b8160200151510361294557845183036128dd576127a3816020015160108151811061279657612796615329565b6020026020010151613434565b96506000875111612836576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128449190614f1b565b82146128d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b505050505050612273565b60008584815181106128f1576128f1615329565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061291c5761291c615329565b6020026020010151905061292f81613594565b955061293c600186615215565b94505050612dc6565b600281602001515103612d3e57600061295d826135b9565b905060008160008151811061297457612974615329565b016020015160f81c9050600061298b600283615358565b61299690600261537a565b905060006129a7848360ff166135dd565b905060006129b58a896135dd565b905060006129c38383613613565b905080835114612a55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612a6a575060ff85166003145b15612c595780825114612aff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b19876020015160018151811061279657612796615329565b9c5060008d5111612bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bba9190614f1b565b8814612c48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b505050505050505050505050612273565b60ff85161580612c6c575060ff85166001145b15612cab57612c988760200151600181518110612c8b57612c8b615329565b6020026020010151613594565b9950612ca4818a615215565b9850612d33565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612dc6565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612dd1816152f1565b915050612495565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612ecd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612eda846136c7565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130d757506000919050565b680755bf798b4a1bf1e58212613149576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff811115613303576133036147ea565b60405190808252806020026020018201604052801561334857816020015b60408051808201909152606080825260208201528152602001906001900390816133215790505b50915060005b818110156133ca57604051806040016040528085838151811061337357613373615329565b602002602001015181526020016133a286848151811061339557613395615329565b602002602001015161379d565b8152508382815181106133b7576133b7615329565b602090810291909101015260010161334e565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613429578060011b82018184015160001a8060041c8253600f8116600183015350506001016133fb565b509295945050505050565b60606000806000613444856137b0565b91945092509050600081600181111561345f5761345f61539d565b146134ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6134f68284615215565b855114613585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b61236d8560200151848461421d565b606060208260000151106135b0576135ab82613434565b6110b2565b6110b2826142b1565b60606110b26135d8836020015160008151811061279657612796615329565b6133d1565b6060825182106135fc57506040805160208101909152600081526110b2565b612273838384865161360e9190614f1b565b6142c7565b6000808251845110613626578251613629565b83515b90505b80821080156136b0575082828151811061364857613648615329565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684838151811061368757613687615329565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136c05781600101915061362c565b5092915050565b6000808211613732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137ab8361449f565b614588565b60008060008084600001511161386e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f8111613893576000600160009450945094505050614216565b60b78111613aa15760006138a8608083614f1b565b905080876000015111613963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806139dc57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613a8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614216915050565b60bf8111613def576000613ab660b783614f1b565b905080876000015111613b71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d1d8184615215565b895111613dd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613ddd836001615215565b97509550600094506142169350505050565b60f78111613ed0576000613e0460c083614f1b565b905080876000015111613ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614216915050565b6000613edd60f783614f1b565b905080876000015111613f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161413a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141448184615215565b8951116141f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614204836001615215565b97509550600194506142169350505050565b9193909250565b60608167ffffffffffffffff811115614238576142386147ea565b6040519080825280601f01601f191660200182016040528015614262576020820181803683370190505b50905081156122735760006142778486615215565b90506020820160005b84811015614298578281015182820152602001614280565b848111156142a7576000858301525b5050509392505050565b60606110b282602001516000846000015161421d565b60608182601f011015614336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8183018451101561440f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561442e5760405191506000825260208201604052614496565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561446757805183526020928301920161444f565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161456a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b60606000806000614598856137b0565b9194509250905060018160018111156145b3576145b361539d565b14614640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161464c8385615215565b146146d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816146f05790505093506000835b86518110156147de576000806147636040518060400160405280858c600001516147479190614f1b565b8152602001858c6020015161475c9190615215565b90526137b0565b50915091506040518060400160405280838361477f9190615215565b8152602001848b602001516147949190615215565b8152508885815181106147a9576147a9615329565b60209081029190910101526147bf600185615215565b93506147cb8183615215565b6147d59084615215565b9250505061471d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614860576148606147ea565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461488a57600080fd5b50565b600082601f83011261489e57600080fd5b813567ffffffffffffffff8111156148b8576148b86147ea565b6148e960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614819565b8181528460208386010111156148fe57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561492d57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614951576149516147ea565b81604052829350843583526020850135915061496c82614868565b8160208401526040850135915061498282614868565b816040840152606085013560608401526080850135608084015260a08501359150808211156149b057600080fd5b506149bd8582860161488d565b60a0830152505092915050565b600080600080600085870360e08112156149e357600080fd5b863567ffffffffffffffff808211156149fb57600080fd5b614a078a838b0161491b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a4057600080fd5b60408901955060c0890135925080831115614a5a57600080fd5b828901925089601f840112614a6e57600080fd5b8235915080821115614a7f57600080fd5b508860208260051b8401011115614a9557600080fd5b959894975092955050506020019190565b60005b83811015614ac1578181015183820152602001614aa9565b83811115614ad0576000848401525b50505050565b60008151808452614aee816020860160208601614aa6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122736020830184614ad6565b600060208284031215614b4557600080fd5b5035919050565b600060208284031215614b5e57600080fd5b813567ffffffffffffffff811115614b7557600080fd5b614b818482850161491b565b949350505050565b803567ffffffffffffffff81168114614ba157600080fd5b919050565b600060208284031215614bb857600080fd5b61227382614b89565b600060208284031215614bd357600080fd5b813561227381614868565b801515811461488a57600080fd5b600080600080600060a08688031215614c0457600080fd5b8535614c0f81614868565b945060208601359350614c2460408701614b89565b92506060860135614c3481614bde565b9150608086013567ffffffffffffffff811115614c5057600080fd5b614c5c8882890161488d565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cbd816049850160208701614aa6565b919091016049019695505050505050565b600060208284031215614ce057600080fd5b815161227381614868565b80516fffffffffffffffffffffffffffffffff81168114614ba157600080fd5b600060608284031215614d1d57600080fd5b6040516060810181811067ffffffffffffffff82111715614d4057614d406147ea565b60405282518152614d5360208401614ceb565b6020820152614d6460408401614ceb565b60408201529392505050565b600060808284031215614d8257600080fd5b6040516080810181811067ffffffffffffffff82111715614da557614da56147ea565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614df157614df16147ea565b8360051b6020614e02818301614819565b868152918501918181019036841115614e1a57600080fd5b865b84811015614e4e57803586811115614e345760008081fd5b614e4036828b0161488d565b845250918301918301614e1c565b50979650505050505050565b600060208284031215614e6c57600080fd5b815161227381614bde565b600060208284031215614e8957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614ee657614ee6614e90565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f1257614f12614e90565b01949350505050565b600082821015614f2d57614f2d614e90565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f7057614f70614f32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fc457614fc4614e90565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561500357615003614e90565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561503757615037614e90565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561507e5761507e614e90565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150b9576150b9614e90565b600087129250878205871284841616156150d5576150d5614e90565b878505871281841616156150eb576150eb614e90565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561513357615133614e90565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561516757615167614e90565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151a5576151a5614e90565b500290565b6000826151b9576151b9614f32565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261520960c0830184614ad6565b98975050505050505050565b6000821982111561522857615228614e90565b500190565b805163ffffffff81168114614ba157600080fd5b805160ff81168114614ba157600080fd5b600060c0828403121561526457600080fd5b60405160c0810181811067ffffffffffffffff82111715615287576152876147ea565b6040526152938361522d565b81526152a160208401615241565b60208201526152b260408401615241565b60408201526152c36060840161522d565b60608201526152d46080840161522d565b60808201526152e560a08401614ceb565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361532257615322614e90565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061536b5761536b614f32565b8060ff84160691505092915050565b600060ff821660ff84168082101561539457615394614e90565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "GUARDIAN()": {}, + "constructor": { + "params": { + "_l2Oracle": "Address of the L2OutputOracle contract.", + "_systemConfig": "Address of the SystemConfig contract." + } + }, + "depositTransaction(address,uint256,uint64,bool,bytes)": { + "params": { + "_data": "Data to trigger the recipient with.", + "_gasLimit": "Amount of L2 gas to purchase by burning gas on L1.", + "_isCreation": "Whether or not the transaction is a contract creation.", + "_to": "Target address on L2.", + "_value": "ETH value to send to the recipient." + } + }, + "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { + "params": { + "_tx": "Withdrawal transaction to finalize." + } + }, + "guardian()": {}, + "initialize(address)": { + "params": { + "_superchainConfig": "Address of the SuperchainConfig contract." + } + }, + "isOutputFinalized(uint256)": { + "params": { + "_l2OutputIndex": "Index of the L2 output to check." + }, + "returns": { + "_0": "Whether or not the output is finalized." + } + }, + "minimumGasLimit(uint64)": { + "params": { + "_byteCount": "Number of bytes in the calldata." + }, + "returns": { + "_0": "The minimum gas limit for a deposit." + } + }, + "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { + "params": { + "_l2OutputIndex": "L2 output index to prove against.", + "_outputRootProof": "Inclusion proof of the L2ToL1MessagePasser contract's storage root.", + "_tx": "Withdrawal transaction to finalize.", + "_withdrawalProof": "Inclusion proof of the withdrawal in L2ToL1MessagePasser contract." + } + } + }, + "events": { + "Paused(address)": { + "params": { + "account": "Address of the account triggering the pause." + } + }, + "TransactionDeposited(address,address,uint256,bytes)": { + "params": { + "from": "Address that triggered the deposit transaction.", + "opaqueData": "ABI encoded deposit data to be parsed off-chain.", + "to": "Address that the deposit transaction is directed to.", + "version": "Version of this deposit transaction event." + } + }, + "Unpaused(address)": { + "params": { + "account": "Address of the account triggering the unpause." + } + }, + "WithdrawalFinalized(bytes32,bool)": { + "params": { + "success": "Whether the withdrawal transaction was successful.", + "withdrawalHash": "Hash of the withdrawal transaction." + } + }, + "WithdrawalProven(bytes32,address,address)": { + "params": { + "from": "Address that triggered the withdrawal transaction.", + "to": "Address that the withdrawal transaction is directed to.", + "withdrawalHash": "Hash of the withdrawal transaction." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"_systemConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"TransactionDeposited\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\",\"indexed\":false}],\"type\":\"event\",\"name\":\"WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"WithdrawalProven\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositTransaction\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"donateETH\"},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Oracle\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_byteCount\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"internalType\":\"struct Types.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}]},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"proveWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"systemConfig\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"GUARDIAN()\":{\"custom:legacy\":\"\"},\"constructor\":{\"params\":{\"_l2Oracle\":\"Address of the L2OutputOracle contract.\",\"_systemConfig\":\"Address of the SystemConfig contract.\"}},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"params\":{\"_data\":\"Data to trigger the recipient with.\",\"_gasLimit\":\"Amount of L2 gas to purchase by burning gas on L1.\",\"_isCreation\":\"Whether or not the transaction is a contract creation.\",\"_to\":\"Target address on L2.\",\"_value\":\"ETH value to send to the recipient.\"}},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"params\":{\"_tx\":\"Withdrawal transaction to finalize.\"}},\"guardian()\":{\"custom:legacy\":\"\"},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract.\"}},\"isOutputFinalized(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the L2 output to check.\"},\"returns\":{\"_0\":\"Whether or not the output is finalized.\"}},\"minimumGasLimit(uint64)\":{\"params\":{\"_byteCount\":\"Number of bytes in the calldata.\"},\"returns\":{\"_0\":\"The minimum gas limit for a deposit.\"}},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"params\":{\"_l2OutputIndex\":\"L2 output index to prove against.\",\"_outputRootProof\":\"Inclusion proof of the L2ToL1MessagePasser contract's storage root.\",\"_tx\":\"Withdrawal transaction to finalize.\",\"_withdrawalProof\":\"Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"L2_ORACLE()\":{\"notice\":\"Address of the L2OutputOracle contract. This will be removed in the future, use `l2Oracle` instead.\"},\"SYSTEM_CONFIG()\":{\"notice\":\"Address of the SystemConfig contract. This will be removed in the future, use `systemConfig` instead.\"},\"constructor\":{\"notice\":\"Constructs the OptimismPortal contract.\"},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"notice\":\"Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience.\"},\"donateETH()\":{\"notice\":\"Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock.\"},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"notice\":\"Finalizes a withdrawal transaction.\"},\"finalizedWithdrawals(bytes32)\":{\"notice\":\"A list of withdrawal hashes which have been successfully finalized.\"},\"guardian()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"isOutputFinalized(uint256)\":{\"notice\":\"Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\"},\"l2Oracle()\":{\"notice\":\"Getter function for the address of the L2OutputOracle on this chain.Address of the L2OutputOracle on this chain.\"},\"l2Sender()\":{\"notice\":\"Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction.\"},\"minimumGasLimit(uint64)\":{\"notice\":\"Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility.\"},\"params()\":{\"notice\":\"EIP-1559 style gas parameters.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"notice\":\"Proves a withdrawal transaction.\"},\"provenWithdrawals(bytes32)\":{\"notice\":\"A mapping of withdrawal hashes to `ProvenWithdrawal` data.\"},\"superchainConfig()\":{\"notice\":\"The address of the Superchain Config contract.\"},\"systemConfig()\":{\"notice\":\"Getter function for the address of the SystemConfig on this chain.Address of the SystemConfig on this chain.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/OptimismPortal.sol\":\"OptimismPortal\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0x663fc35cd5af00e3e2ccbf57f1865a73cd717116f04c5bd89c5b131ae21c54d7\",\"urls\":[\"bzz-raw://0f4ad3864a4382d932fa8d75dd8b9bb189c45fc7a9b25a73bfdd7a2774a3e158\",\"dweb:/ipfs/QmYCKtRp1WQGFiWu4HcLWJmKwNeYiRoborXQcT8kx3c7P8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47332, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 47335, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 77959, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "params", + "offset": 0, + "slot": "1", + "type": "t_struct(ResourceParams)77942_storage" + }, + { + "astId": 77964, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)48_storage" + }, + { + "astId": 77040, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "l2Sender", + "offset": 0, + "slot": "50", + "type": "t_address" + }, + { + "astId": 77045, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "finalizedWithdrawals", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 77051, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "provenWithdrawals", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)77021_storage)" + }, + { + "astId": 77054, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "spacer_53_0_1", + "offset": 0, + "slot": "53", + "type": "t_bool" + }, + { + "astId": 77058, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "superchainConfig", + "offset": 1, + "slot": "53", + "type": "t_contract(SuperchainConfig)78483" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)48_storage": { + "encoding": "inplace", + "label": "uint256[48]", + "numberOfBytes": "1536", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(SuperchainConfig)78483": { + "encoding": "inplace", + "label": "contract SuperchainConfig", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)77021_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)", + "numberOfBytes": "32", + "value": "t_struct(ProvenWithdrawal)77021_storage" + }, + "t_struct(ProvenWithdrawal)77021_storage": { + "encoding": "inplace", + "label": "struct OptimismPortal.ProvenWithdrawal", + "numberOfBytes": "64", + "members": [ + { + "astId": 77016, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "outputRoot", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 77018, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "timestamp", + "offset": 0, + "slot": "1", + "type": "t_uint128" + }, + { + "astId": 77020, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "l2OutputIndex", + "offset": 16, + "slot": "1", + "type": "t_uint128" + } + ] + }, + "t_struct(ResourceParams)77942_storage": { + "encoding": "inplace", + "label": "struct ResourceMetering.ResourceParams", + "numberOfBytes": "32", + "members": [ + { + "astId": 77937, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "prevBaseFee", + "offset": 0, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 77939, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "prevBoughtGas", + "offset": 16, + "slot": "0", + "type": "t_uint64" + }, + { + "astId": 77941, + "contract": "src/L1/OptimismPortal.sol:OptimismPortal", + "label": "prevBlockNum", + "offset": 24, + "slot": "0", + "type": "t_uint64" + } + ] + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0xbb6bbf87fe919d99c14b0a558bc55acb270b332417250186180ba19615f6dfff", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "GUARDIAN()": { + "notice": "Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian." + }, + "L2_ORACLE()": { + "notice": "Address of the L2OutputOracle contract. This will be removed in the future, use `l2Oracle` instead." + }, + "SYSTEM_CONFIG()": { + "notice": "Address of the SystemConfig contract. This will be removed in the future, use `systemConfig` instead." + }, + "constructor": { + "notice": "Constructs the OptimismPortal contract." + }, + "depositTransaction(address,uint256,uint64,bool,bytes)": { + "notice": "Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience." + }, + "donateETH()": { + "notice": "Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock." + }, + "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { + "notice": "Finalizes a withdrawal transaction." + }, + "finalizedWithdrawals(bytes32)": { + "notice": "A list of withdrawal hashes which have been successfully finalized." + }, + "guardian()": { + "notice": "Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian." + }, + "initialize(address)": { + "notice": "Initializer." + }, + "isOutputFinalized(uint256)": { + "notice": "Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise." + }, + "l2Oracle()": { + "notice": "Getter function for the address of the L2OutputOracle on this chain.Address of the L2OutputOracle on this chain." + }, + "l2Sender()": { + "notice": "Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction." + }, + "minimumGasLimit(uint64)": { + "notice": "Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility." + }, + "params()": { + "notice": "EIP-1559 style gas parameters." + }, + "paused()": { + "notice": "Getter for the current paused status." + }, + "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { + "notice": "Proves a withdrawal transaction." + }, + "provenWithdrawals(bytes32)": { + "notice": "A mapping of withdrawal hashes to `ProvenWithdrawal` data." + }, + "superchainConfig()": { + "notice": "The address of the Superchain Config contract." + }, + "systemConfig()": { + "notice": "Getter function for the address of the SystemConfig on this chain.Address of the SystemConfig on this chain." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "Paused(address)": { + "notice": "Emitted when the pause is triggered." + }, + "TransactionDeposited(address,address,uint256,bytes)": { + "notice": "Emitted when a transaction is deposited from L1 to L2. The parameters of this event are read by the rollup node and used to derive deposit transactions on L2." + }, + "Unpaused(address)": { + "notice": "Emitted when the pause is lifted." + }, + "WithdrawalFinalized(bytes32,bool)": { + "notice": "Emitted when a withdrawal transaction is finalized." + }, + "WithdrawalProven(bytes32,address,address)": { + "notice": "Emitted when a withdrawal transaction is proven." + } + }, + "notice": "The OptimismPortal is a low-level contract responsible for passing messages between L1 and L2. Messages sent directly to the OptimismPortal have no form of replayability. Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/OptimismPortalProxy.json b/e2e/deployments/devnetL1/OptimismPortalProxy.json new file mode 100644 index 000000000000..b2e55c108888 --- /dev/null +++ b/e2e/deployments/devnetL1/OptimismPortalProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x4859725d8f2f49aE689512eE5F150FdcB76cd72c", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x2009edb23616fc5433532191eefb9038e24b38179e753fb1c1e43f54de859e48", + "transactionIndex": "0xd", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x92c59d", + "gasUsed": "0x80250", + "contractAddress": "0x4859725d8f2f49aE689512eE5F150FdcB76cd72c", + "logs": [ + { + "address": "0x4859725d8f2f49aE689512eE5F150FdcB76cd72c", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0x2009edb23616fc5433532191eefb9038e24b38179e753fb1c1e43f54de859e48", + "transactionIndex": "0xd", + "logIndex": "0x1a", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x2009edb23616fc5433532191eefb9038e24b38179e753fb1c1e43f54de859e48", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/PreimageOracle.json b/e2e/deployments/devnetL1/PreimageOracle.json new file mode 100644 index 000000000000..c8dd256899d5 --- /dev/null +++ b/e2e/deployments/devnetL1/PreimageOracle.json @@ -0,0 +1,316 @@ +{ + "abi": [ + { + "type": "function", + "name": "loadKeccak256PreimagePart", + "inputs": [ + { + "name": "_partOffset", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_preimage", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "loadLocalData", + "inputs": [ + { + "name": "_ident", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_localContext", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_word", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_size", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_partOffset", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "key_", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "preimageLengths", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "preimagePartOk", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "preimageParts", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "readPreimage", + "inputs": [ + { + "name": "_key", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_offset", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "dat_", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "datLen_", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "error", + "name": "PartOffsetOOB", + "inputs": [] + } + ], + "address": "0xb018cA14112C15D21d0FB22568fe4475A58EDFc0", + "args": [], + "bytecode": "0x608060405234801561001057600080fd5b5061063c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063e03110e111610050578063e03110e114610106578063e15926111461012e578063fef2b4ed1461014357600080fd5b806352f0f3ad1461007757806361238bde1461009d5780638542cf50146100c8575b600080fd5b61008a6100853660046104df565b610163565b6040519081526020015b60405180910390f35b61008a6100ab36600461051a565b600160209081526000928352604080842090915290825290205481565b6100f66100d636600461051a565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610094565b61011961011436600461051a565b610238565b60408051928352602083019190915201610094565b61014161013c36600461053c565b610329565b005b61008a6101513660046105b8565b60006020819052908152604090205481565b600061016f8686610432565b905061017c836008610600565b8211806101895750602083115b156101c0576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6000828152600260209081526040808320848452909152812054819060ff166102c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102dd816008610600565b6102e8856020610600565b1061030657836102f9826008610600565b6103039190610618565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018611156103485763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176104d8818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b600080600080600060a086880312156104f757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806040838503121561052d57600080fd5b50508035926020909101359150565b60008060006040848603121561055157600080fd5b83359250602084013567ffffffffffffffff8082111561057057600080fd5b818601915086601f83011261058457600080fd5b81358181111561059357600080fd5b8760208285010111156105a557600080fd5b6020830194508093505050509250925092565b6000602082840312156105ca57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610613576106136105d1565b500190565b60008282101561062a5761062a6105d1565b50039056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063e03110e111610050578063e03110e114610106578063e15926111461012e578063fef2b4ed1461014357600080fd5b806352f0f3ad1461007757806361238bde1461009d5780638542cf50146100c8575b600080fd5b61008a6100853660046104df565b610163565b6040519081526020015b60405180910390f35b61008a6100ab36600461051a565b600160209081526000928352604080842090915290825290205481565b6100f66100d636600461051a565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610094565b61011961011436600461051a565b610238565b60408051928352602083019190915201610094565b61014161013c36600461053c565b610329565b005b61008a6101513660046105b8565b60006020819052908152604090205481565b600061016f8686610432565b905061017c836008610600565b8211806101895750602083115b156101c0576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6000828152600260209081526040808320848452909152812054819060ff166102c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102dd816008610600565b6102e8856020610600565b1061030657836102f9826008610600565b6103039190610618565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018611156103485763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176104d8818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b600080600080600060a086880312156104f757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806040838503121561052d57600080fd5b50508035926020909101359150565b60008060006040848603121561055157600080fd5b83359250602084013567ffffffffffffffff8082111561057057600080fd5b818601915086601f83011261058457600080fd5b81358181111561059357600080fd5b8760208285010111156105a557600080fd5b6020830194508093505050509250925092565b6000602082840312156105ca57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610613576106136105d1565b500190565b60008282101561062a5761062a6105d1565b50039056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "loadKeccak256PreimagePart(uint256,bytes)": { + "params": { + "_partOffset": "The offset of the preimage to read.", + "_preimage": "The preimage data." + } + }, + "loadLocalData(uint256,bytes32,bytes32,uint256,uint256)": { + "details": "The local data parts are loaded into the preimage oracle under the context of the caller - no other account can write to the caller's context specific data. There are 5 local data identifiers: ┌────────────┬────────────────────────┐ │ Identifier │ Data │ ├────────────┼────────────────────────┤ │ 1 │ L1 Head Hash (bytes32) │ │ 2 │ Output Root (bytes32) │ │ 3 │ Root Claim (bytes32) │ │ 4 │ L2 Block Number (u64) │ │ 5 │ Chain ID (u64) │ └────────────┴────────────────────────┘", + "params": { + "_ident": "The identifier of the local data.", + "_localContext": "The local key context for the preimage oracle. Optionally, can be set as a constant if the caller only requires one set of local keys.", + "_partOffset": "The offset of the local data part to write to the oracle.", + "_size": "The number of bytes in `_word` to load.", + "_word": "The local data word." + } + }, + "readPreimage(bytes32,uint256)": { + "params": { + "_key": "The key of the preimage to read.", + "_offset": "The offset of the preimage to read." + }, + "returns": { + "datLen_": "The length of the preimage data.", + "dat_": "The preimage data." + } + } + }, + "title": "PreimageOracle" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"type\":\"error\",\"name\":\"PartOffsetOOB\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_preimage\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"loadKeccak256PreimagePart\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ident\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_localContext\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_word\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"loadLocalData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"key_\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"preimageLengths\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"preimagePartOk\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"preimageParts\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"readPreimage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"dat_\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"datLen_\",\"type\":\"uint256\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"loadKeccak256PreimagePart(uint256,bytes)\":{\"params\":{\"_partOffset\":\"The offset of the preimage to read.\",\"_preimage\":\"The preimage data.\"}},\"loadLocalData(uint256,bytes32,bytes32,uint256,uint256)\":{\"details\":\"The local data parts are loaded into the preimage oracle under the context of the caller - no other account can write to the caller's context specific data. There are 5 local data identifiers: ┌────────────┬────────────────────────┐ │ Identifier │ Data │ ├────────────┼────────────────────────┤ │ 1 │ L1 Head Hash (bytes32) │ │ 2 │ Output Root (bytes32) │ │ 3 │ Root Claim (bytes32) │ │ 4 │ L2 Block Number (u64) │ │ 5 │ Chain ID (u64) │ └────────────┴────────────────────────┘\",\"params\":{\"_ident\":\"The identifier of the local data.\",\"_localContext\":\"The local key context for the preimage oracle. Optionally, can be set as a constant if the caller only requires one set of local keys.\",\"_partOffset\":\"The offset of the local data part to write to the oracle.\",\"_size\":\"The number of bytes in `_word` to load.\",\"_word\":\"The local data word.\"}},\"readPreimage(bytes32,uint256)\":{\"params\":{\"_key\":\"The key of the preimage to read.\",\"_offset\":\"The offset of the preimage to read.\"},\"returns\":{\"datLen_\":\"The length of the preimage data.\",\"dat_\":\"The preimage data.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"loadKeccak256PreimagePart(uint256,bytes)\":{\"notice\":\"Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes (clipped at preimage length, if out of data).\"},\"loadLocalData(uint256,bytes32,bytes32,uint256,uint256)\":{\"notice\":\"Loads of local data part into the preimage oracle.\"},\"preimageLengths(bytes32)\":{\"notice\":\"Mapping of pre-image keys to pre-image lengths.\"},\"preimagePartOk(bytes32,uint256)\":{\"notice\":\"Mapping of pre-image keys to pre-image part offsets.\"},\"preimageParts(bytes32,uint256)\":{\"notice\":\"Mapping of pre-image keys to pre-image parts.\"},\"readPreimage(bytes32,uint256)\":{\"notice\":\"Reads a preimage from the oracle.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/cannon/PreimageOracle.sol\":\"PreimageOracle\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"src/cannon/PreimageKeyLib.sol\":{\"keccak256\":\"0x082e910b8a3f523ac0920f0bc5a09e127fe9e48127694e5a0efce820d4654e85\",\"urls\":[\"bzz-raw://bce8c13880b75f2d8561188279b2333c455c831216fc29375570d9c93767c6cc\",\"dweb:/ipfs/QmRmworxD49TBLcLS81sNUEfkQVgg3tf2L6pUDCduDJvWm\"],\"license\":\"MIT\"},\"src/cannon/PreimageOracle.sol\":{\"keccak256\":\"0x183526aee1bf6b349b4d7c0baca2437804830cf4b7ac5f0c42acca9f7b3c3d95\",\"urls\":[\"bzz-raw://1c8e34916bb5236c775bbcc795a942e38b98e3eb8609f0f1c3a540d681679013\",\"dweb:/ipfs/QmUB6Uf3U9MRm73jqeYeUgB18aY1L5bmvvp1YmGXTfedJY\"],\"license\":\"MIT\"},\"src/cannon/interfaces/IPreimageOracle.sol\":{\"keccak256\":\"0xbba7c884cae96e8891ffa27de01049cc763665a8c009f7bb09572a56009cebe0\",\"urls\":[\"bzz-raw://dcda03b5007b6f0053e721fbbd9850ead181ea7366bc826294bfe1fb812c8e7c\",\"dweb:/ipfs/QmUKTfc13UnzMgKoghCmCdYHc35y1tRLBADFWgxibPbSxX\"],\"license\":\"MIT\"},\"src/cannon/libraries/CannonErrors.sol\":{\"keccak256\":\"0xf1783e6de2a36fd27080e939077187dfda61b1b93aae129c9c06e86909a384b5\",\"urls\":[\"bzz-raw://b437f5488aec80b1defe68f3ce8a500a308c12f72bb8c8d8177c63bd6a89219d\",\"dweb:/ipfs/QmYQaJvJhe7kPvvVweApH41ryvFui9XVHvhZSKMdZ5B439\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 83933, + "contract": "src/cannon/PreimageOracle.sol:PreimageOracle", + "label": "preimageLengths", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_uint256)" + }, + { + "astId": 83940, + "contract": "src/cannon/PreimageOracle.sol:PreimageOracle", + "label": "preimageParts", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))" + }, + { + "astId": 83947, + "contract": "src/cannon/PreimageOracle.sol:PreimageOracle", + "label": "preimagePartOk", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint256 => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_bool)" + }, + "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint256 => bytes32))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_bytes32)" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_bool)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_bytes32)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0x70eb9ad9de573d31d0c25ad68d2ad566fdb8f58d1d05e033126310f36ac1583b", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "loadKeccak256PreimagePart(uint256,bytes)": { + "notice": "Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes (clipped at preimage length, if out of data)." + }, + "loadLocalData(uint256,bytes32,bytes32,uint256,uint256)": { + "notice": "Loads of local data part into the preimage oracle." + }, + "preimageLengths(bytes32)": { + "notice": "Mapping of pre-image keys to pre-image lengths." + }, + "preimagePartOk(bytes32,uint256)": { + "notice": "Mapping of pre-image keys to pre-image part offsets." + }, + "preimageParts(bytes32,uint256)": { + "notice": "Mapping of pre-image keys to pre-image parts." + }, + "readPreimage(bytes32,uint256)": { + "notice": "Reads a preimage from the oracle." + } + }, + "errors": { + "PartOffsetOOB()": [ + { + "notice": "Thrown when a passed part offset is out of bounds." + } + ] + }, + "notice": "A contract for storing permissioned pre-images." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/ProtocolVersions.json b/e2e/deployments/devnetL1/ProtocolVersions.json new file mode 100644 index 000000000000..64a697743d05 --- /dev/null +++ b/e2e/deployments/devnetL1/ProtocolVersions.json @@ -0,0 +1,407 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "RECOMMENDED_SLOT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "REQUIRED_SLOT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "VERSION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_required", + "type": "uint256", + "internalType": "ProtocolVersion" + }, + { + "name": "_recommended", + "type": "uint256", + "internalType": "ProtocolVersion" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "recommended", + "inputs": [], + "outputs": [ + { + "name": "out_", + "type": "uint256", + "internalType": "ProtocolVersion" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "required", + "inputs": [], + "outputs": [ + { + "name": "out_", + "type": "uint256", + "internalType": "ProtocolVersion" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "setRecommended", + "inputs": [ + { + "name": "_recommended", + "type": "uint256", + "internalType": "ProtocolVersion" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setRequired", + "inputs": [ + { + "name": "_required", + "type": "uint256", + "internalType": "ProtocolVersion" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ConfigUpdate", + "inputs": [ + { + "name": "version", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "updateType", + "type": "uint8", + "indexed": true, + "internalType": "enum ProtocolVersions.UpdateType" + }, + { + "name": "data", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "args": [], + "bytecode": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b6200051c565b600054610100900460ff1615808015620000495750600054600160ff909116105b8062000079575062000066306200017e60201b6200053f1760201c565b15801562000079575060005460ff166001145b620000e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000106576000805461ff0019166101001790555b620001106200018d565b6200011b84620001f5565b620001268362000274565b620001318262000324565b801562000178576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f362000385565b565b620001ff620003ec565b6001600160a01b038116620002665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000d9565b620002718162000448565b50565b620002ba620002a560017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200049e565b60001b826200049a60201b6200055b1760201c565b600081604051602001620002d091815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620003189190620004c4565b60405180910390a35050565b62000355620002a560017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200049e565b6000816040516020016200036b91815260200190565b60408051601f1981840301815291905290506001620002e5565b600054610100900460ff16620003e15760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f33362000448565b6033546001600160a01b03163314620001f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000d9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b600082821015620004bf57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004f357858101830151858201604001528201620004d5565b8181111562000506576000604083870101525b50601f01601f1916929092016040019392505050565b610a23806200052c6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "initialize(address,uint256,uint256)": { + "params": { + "_owner": "Initial owner of the contract.", + "_recommended": "Recommended protocol version to operate on thi chain.", + "_required": "Required protocol version to operate on this chain." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "recommended()": { + "returns": { + "out_": "Recommended protocol version to sync to the head of the chain." + } + }, + "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." + }, + "required()": { + "returns": { + "out_": "Required protocol version to sync to the head of the chain." + } + }, + "setRecommended(uint256)": { + "params": { + "_recommended": "New recommended protocol version." + } + }, + "setRequired(uint256)": { + "params": { + "_required": "New required protocol version." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "params": { + "data": "Encoded update data.", + "updateType": "Type of update.", + "version": "ProtocolVersion version." + } + } + }, + "title": "ProtocolVersions" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum ProtocolVersions.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RECOMMENDED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"REQUIRED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"recommended\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"required\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRecommended\"},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRequired\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256)\":{\"params\":{\"_owner\":\"Initial owner of the contract.\",\"_recommended\":\"Recommended protocol version to operate on thi chain.\",\"_required\":\"Required protocol version to operate on this chain.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recommended()\":{\"returns\":{\"out_\":\"Recommended protocol version to sync to the head of the chain.\"}},\"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.\"},\"required()\":{\"returns\":{\"out_\":\"Required protocol version to sync to the head of the chain.\"}},\"setRecommended(uint256)\":{\"params\":{\"_recommended\":\"New recommended protocol version.\"}},\"setRequired(uint256)\":{\"params\":{\"_required\":\"New required protocol version.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"RECOMMENDED_SLOT()\":{\"notice\":\"Storage slot that the recommended protocol version is stored at.\"},\"REQUIRED_SLOT()\":{\"notice\":\"Storage slot that the required protocol version is stored at.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"constructor\":{\"notice\":\"Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes.\"},\"initialize(address,uint256,uint256)\":{\"notice\":\"Initializer.\"},\"recommended()\":{\"notice\":\"High level getter for the recommended protocol version.\"},\"required()\":{\"notice\":\"High level getter for the required protocol version.\"},\"setRecommended(uint256)\":{\"notice\":\"Updates the recommended protocol version. Can only be called by the owner.\"},\"setRequired(uint256)\":{\"notice\":\"Updates the required protocol version. Can only be called by the owner.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/ProtocolVersions.sol\":\"ProtocolVersions\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ProtocolVersions.sol\":{\"keccak256\":\"0x83182a9b71c648f9a5ee7a3b572df4e038857c464379aa9cf45d0a74325acf83\",\"urls\":[\"bzz-raw://69573d2de0bdcdb6f1d34a49072976de0738344372f8364104b2fd35e3dca367\",\"dweb:/ipfs/QmU1UJV14EJtDsa96d7jX4giPgUtPPJB9S2xGddarDjZj2\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 44768, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 44771, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 46299, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 44640, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 44760, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x62c43905635be4331b24cdb033755a20388af34ca029cb7aaa54933ecc5679eb", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "RECOMMENDED_SLOT()": { + "notice": "Storage slot that the recommended protocol version is stored at." + }, + "REQUIRED_SLOT()": { + "notice": "Storage slot that the required protocol version is stored at." + }, + "VERSION()": { + "notice": "Version identifier, used for upgrades." + }, + "constructor": { + "notice": "Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes." + }, + "initialize(address,uint256,uint256)": { + "notice": "Initializer." + }, + "recommended()": { + "notice": "High level getter for the recommended protocol version." + }, + "required()": { + "notice": "High level getter for the required protocol version." + }, + "setRecommended(uint256)": { + "notice": "Updates the recommended protocol version. Can only be called by the owner." + }, + "setRequired(uint256)": { + "notice": "Updates the required protocol version. Can only be called by the owner." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "notice": "Emitted when configuration is updated." + } + }, + "notice": "The ProtocolVersions contract is used to manage superchain protocol version information." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/ProtocolVersionsProxy.json b/e2e/deployments/devnetL1/ProtocolVersionsProxy.json new file mode 100644 index 000000000000..ef45bc2d0849 --- /dev/null +++ b/e2e/deployments/devnetL1/ProtocolVersionsProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x98Af98D8c970F6df96136ea072ECa319d8A6d320", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x10678ca07743cc88df587a035ad9dd2f0274a5d04d62978851413dd5bd77b70b", + "transactionIndex": "0xa", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x7de9e6", + "gasUsed": "0x80250", + "contractAddress": "0x98Af98D8c970F6df96136ea072ECa319d8A6d320", + "logs": [ + { + "address": "0x98Af98D8c970F6df96136ea072ECa319d8A6d320", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0x10678ca07743cc88df587a035ad9dd2f0274a5d04d62978851413dd5bd77b70b", + "transactionIndex": "0xa", + "logIndex": "0xd", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000004000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x10678ca07743cc88df587a035ad9dd2f0274a5d04d62978851413dd5bd77b70b", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/ProxyAdmin.json b/e2e/deployments/devnetL1/ProxyAdmin.json new file mode 100644 index 000000000000..6e39af97d8f3 --- /dev/null +++ b/e2e/deployments/devnetL1/ProxyAdmin.json @@ -0,0 +1,579 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "addressManager", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract AddressManager" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "changeProxyAdmin", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address payable" + }, + { + "name": "_newAdmin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getProxyAdmin", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address payable" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProxyImplementation", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "implementationName", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isUpgrading", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proxyType", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum ProxyAdmin.ProxyType" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setAddress", + "inputs": [ + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setAddressManager", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "contract AddressManager" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setImplementationName", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + }, + { + "name": "_name", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setProxyType", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + }, + { + "name": "_type", + "type": "uint8", + "internalType": "enum ProxyAdmin.ProxyType" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setUpgrading", + "inputs": [ + { + "name": "_upgrading", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address payable" + }, + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeAndCall", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address payable" + }, + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x1D4ed8572c78bf7146358183694284453C5B0C58", + "args": [ + "0x78697c88847DFbbB40523E42c1f2e28a13A170bE" + ], + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", + "deployedBytecode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "changeProxyAdmin(address,address)": { + "params": { + "_newAdmin": "Address of the new proxy admin.", + "_proxy": "Address of the proxy to update." + } + }, + "constructor": { + "params": { + "_owner": "Address of the initial owner of this contract." + } + }, + "getProxyAdmin(address)": { + "params": { + "_proxy": "Address of the proxy to get the admin of." + }, + "returns": { + "_0": "Address of the admin of the proxy." + } + }, + "getProxyImplementation(address)": { + "params": { + "_proxy": "Address of the proxy to get the implementation of." + }, + "returns": { + "_0": "Address of the implementation of the proxy." + } + }, + "isUpgrading()": { + "returns": { + "_0": "Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy." + } + }, + "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." + }, + "setAddress(string,address)": { + "params": { + "_address": "Address to attach to the given name.", + "_name": "Name to set within the AddressManager." + } + }, + "setAddressManager(address)": { + "params": { + "_address": "Address of the AddressManager." + } + }, + "setImplementationName(address,string)": { + "params": { + "_address": "Address of the ResolvedDelegateProxy.", + "_name": "Name of the implementation for the proxy." + } + }, + "setProxyType(address,uint8)": { + "params": { + "_address": "Address of the proxy.", + "_type": "Type of the proxy." + } + }, + "setUpgrading(bool)": { + "params": { + "_upgrading": "Whether or not the system is upgrading." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgrade(address,address)": { + "params": { + "_implementation": "Address of the new implementation address.", + "_proxy": "Address of the proxy to upgrade." + } + }, + "upgradeAndCall(address,address,bytes)": { + "params": { + "_data": "Data to trigger the new implementation with.", + "_implementation": "Address of the new implementation address.", + "_proxy": "Address of the proxy to upgrade." + } + } + }, + "title": "ProxyAdmin" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"addressManager\",\"outputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newAdmin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeProxyAdmin\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"implementationName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isUpgrading\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proxyType\",\"outputs\":[{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"\",\"type\":\"uint8\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddressManager\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setImplementationName\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"_type\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setProxyType\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_upgrading\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUpgrading\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgrade\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeAndCall\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"params\":{\"_newAdmin\":\"Address of the new proxy admin.\",\"_proxy\":\"Address of the proxy to update.\"}},\"constructor\":{\"params\":{\"_owner\":\"Address of the initial owner of this contract.\"}},\"getProxyAdmin(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the admin of.\"},\"returns\":{\"_0\":\"Address of the admin of the proxy.\"}},\"getProxyImplementation(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the implementation of.\"},\"returns\":{\"_0\":\"Address of the implementation of the proxy.\"}},\"isUpgrading()\":{\"custom:legacy\":\"@notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\",\"returns\":{\"_0\":\"Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\"}},\"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.\"},\"setAddress(string,address)\":{\"custom:legacy\":\"@notice Set an address in the address manager. Since only the owner of the AddressManager can directly modify addresses and the ProxyAdmin will own the AddressManager, this gives the owner of the ProxyAdmin the ability to modify addresses directly.\",\"params\":{\"_address\":\"Address to attach to the given name.\",\"_name\":\"Name to set within the AddressManager.\"}},\"setAddressManager(address)\":{\"params\":{\"_address\":\"Address of the AddressManager.\"}},\"setImplementationName(address,string)\":{\"params\":{\"_address\":\"Address of the ResolvedDelegateProxy.\",\"_name\":\"Name of the implementation for the proxy.\"}},\"setProxyType(address,uint8)\":{\"params\":{\"_address\":\"Address of the proxy.\",\"_type\":\"Type of the proxy.\"}},\"setUpgrading(bool)\":{\"custom:legacy\":\"@notice Set the upgrading status for the Chugsplash proxy type.\",\"params\":{\"_upgrading\":\"Whether or not the system is upgrading.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"params\":{\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}},\"upgradeAndCall(address,address,bytes)\":{\"params\":{\"_data\":\"Data to trigger the new implementation with.\",\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addressManager()\":{\"notice\":\"The address of the address manager, this is required to manage the ResolvedDelegateProxy type.\"},\"changeProxyAdmin(address,address)\":{\"notice\":\"Updates the admin of the given proxy address.\"},\"getProxyAdmin(address)\":{\"notice\":\"Returns the admin of the given proxy address.\"},\"getProxyImplementation(address)\":{\"notice\":\"Returns the implementation of the given proxy address.\"},\"implementationName(address)\":{\"notice\":\"A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type.\"},\"proxyType(address)\":{\"notice\":\"A mapping of proxy types, used for backwards compatibility.\"},\"setAddressManager(address)\":{\"notice\":\"Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts.\"},\"setImplementationName(address,string)\":{\"notice\":\"Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name.\"},\"setProxyType(address,uint8)\":{\"notice\":\"Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types.\"},\"upgrade(address,address)\":{\"notice\":\"Changes a proxy's implementation contract.\"},\"upgradeAndCall(address,address,bytes)\":{\"notice\":\"Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0xdde5626645fa217ad3a37805c4c3012e4251de01df868aae73b986f5d03cdb23\",\"urls\":[\"bzz-raw://a99fd0ec440c17c826465001dc88c5185dd41dc72396254fdd3cdfcc84aeae8c\",\"dweb:/ipfs/QmStHuecN89zBL8FH9SUK1TtkyYwfzMY2KkQaFJLHZLuyA\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"},\"src/universal/ProxyAdmin.sol\":{\"keccak256\":\"0xd15267cf5ed8c24d5a0f2099b8d470178d7ad729db52be16232eb143620b8dcf\",\"urls\":[\"bzz-raw://e9300ee0feb16fcf6c06ee541f2496eac533256bd97f79fe2128527d2f096894\",\"dweb:/ipfs/Qme3Md8pGSnjkG94WFXUdi5UF3a47BTQgKCdGmTKcMgcRa\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xabcbb5e3b2c2158b89afe2114656f54a1db33c6134880923e9619be590e39a0b", + "transactionIndex": "0x4", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x610467", + "gasUsed": "0x16a4b9", + "contractAddress": "0x1D4ed8572c78bf7146358183694284453C5B0C58", + "logs": [ + { + "address": "0x1D4ed8572c78bf7146358183694284453C5B0C58", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be" + ], + "data": "0x", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0xabcbb5e3b2c2158b89afe2114656f54a1db33c6134880923e9619be590e39a0b", + "transactionIndex": "0x4", + "logIndex": "0x3", + "removed": false + }, + { + "address": "0x1D4ed8572c78bf7146358183694284453C5B0C58", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be" + ], + "data": "0x", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0xabcbb5e3b2c2158b89afe2114656f54a1db33c6134880923e9619be590e39a0b", + "transactionIndex": "0x4", + "logIndex": "0x4", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000001000000000000000000000000000000000000020000010000000000000800000000000000000000000000000000400001000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47128, + "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 97050, + "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", + "label": "proxyType", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_enum(ProxyType)97044)" + }, + { + "astId": 97055, + "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", + "label": "implementationName", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_string_storage)" + }, + { + "astId": 97059, + "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", + "label": "addressManager", + "offset": 0, + "slot": "3", + "type": "t_contract(AddressManager)88492" + }, + { + "astId": 97062, + "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", + "label": "upgrading", + "offset": 20, + "slot": "3", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(AddressManager)88492": { + "encoding": "inplace", + "label": "contract AddressManager", + "numberOfBytes": "20" + }, + "t_enum(ProxyType)97044": { + "encoding": "inplace", + "label": "enum ProxyAdmin.ProxyType", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_enum(ProxyType)97044)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => enum ProxyAdmin.ProxyType)", + "numberOfBytes": "32", + "value": "t_enum(ProxyType)97044" + }, + "t_mapping(t_address,t_string_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0xabcbb5e3b2c2158b89afe2114656f54a1db33c6134880923e9619be590e39a0b", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "addressManager()": { + "notice": "The address of the address manager, this is required to manage the ResolvedDelegateProxy type." + }, + "changeProxyAdmin(address,address)": { + "notice": "Updates the admin of the given proxy address." + }, + "getProxyAdmin(address)": { + "notice": "Returns the admin of the given proxy address." + }, + "getProxyImplementation(address)": { + "notice": "Returns the implementation of the given proxy address." + }, + "implementationName(address)": { + "notice": "A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type." + }, + "proxyType(address)": { + "notice": "A mapping of proxy types, used for backwards compatibility." + }, + "setAddressManager(address)": { + "notice": "Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts." + }, + "setImplementationName(address,string)": { + "notice": "Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name." + }, + "setProxyType(address,uint8)": { + "notice": "Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types." + }, + "upgrade(address,address)": { + "notice": "Changes a proxy's implementation contract." + }, + "upgradeAndCall(address,address,bytes)": { + "notice": "Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls." + } + }, + "notice": "This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, based on the OpenZeppelin implementation. It has backwards compatibility logic to work with the various types of proxies that have been deployed by Optimism in the past." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SafeProxyFactory.json b/e2e/deployments/devnetL1/SafeProxyFactory.json new file mode 100644 index 000000000000..ddf8abedf101 --- /dev/null +++ b/e2e/deployments/devnetL1/SafeProxyFactory.json @@ -0,0 +1,226 @@ +{ + "abi": [ + { + "type": "function", + "name": "createChainSpecificProxyWithNonce", + "inputs": [ + { + "name": "_singleton", + "type": "address", + "internalType": "address" + }, + { + "name": "initializer", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "saltNonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "proxy", + "type": "address", + "internalType": "contract SafeProxy" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "createProxyWithCallback", + "inputs": [ + { + "name": "_singleton", + "type": "address", + "internalType": "address" + }, + { + "name": "initializer", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "saltNonce", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "callback", + "type": "address", + "internalType": "contract IProxyCreationCallback" + } + ], + "outputs": [ + { + "name": "proxy", + "type": "address", + "internalType": "contract SafeProxy" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "createProxyWithNonce", + "inputs": [ + { + "name": "_singleton", + "type": "address", + "internalType": "address" + }, + { + "name": "initializer", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "saltNonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "proxy", + "type": "address", + "internalType": "contract SafeProxy" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getChainId", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proxyCreationCode", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "pure" + }, + { + "type": "event", + "name": "ProxyCreation", + "inputs": [ + { + "name": "proxy", + "type": "address", + "indexed": true, + "internalType": "contract SafeProxy" + }, + { + "name": "singleton", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x762C3f4f81a35fE4c224731dd0531CDA02fb2FE3", + "args": [], + "bytecode": "0x608060405234801561001057600080fd5b50610913806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "author": "Stefan George - @Georgi87", + "methods": { + "createChainSpecificProxyWithNonce(address,bytes,uint256)": { + "details": "Allows to create a new proxy contract that should exist only on 1 network (e.g. specific governance or admin accounts) by including the chain id in the create2 salt. Such proxies cannot be created on other networks by replaying the transaction.", + "params": { + "_singleton": "Address of singleton contract. Must be deployed at the time of execution.", + "initializer": "Payload for a message call to be sent to a new proxy contract.", + "saltNonce": "Nonce that will be used to generate the salt to calculate the address of the new proxy contract." + } + }, + "createProxyWithCallback(address,bytes,uint256,address)": { + "params": { + "_singleton": "Address of singleton contract. Must be deployed at the time of execution.", + "callback": "Callback that will be invoked after the new proxy contract has been successfully deployed and initialized.", + "initializer": "Payload for a message call to be sent to a new proxy contract.", + "saltNonce": "Nonce that will be used to generate the salt to calculate the address of the new proxy contract." + } + }, + "createProxyWithNonce(address,bytes,uint256)": { + "params": { + "_singleton": "Address of singleton contract. Must be deployed at the time of execution.", + "initializer": "Payload for a message call to be sent to a new proxy contract.", + "saltNonce": "Nonce that will be used to generate the salt to calculate the address of the new proxy contract." + } + }, + "getChainId()": { + "returns": { + "_0": "The ID of the current chain as a uint256." + } + }, + "proxyCreationCode()": { + "details": "Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address." + } + }, + "title": "Proxy Factory - Allows to create a new proxy contract and execute a message call to the new proxy within one transaction." + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract SafeProxy\",\"name\":\"proxy\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"singleton\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ProxyCreation\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_singleton\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"initializer\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"saltNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createChainSpecificProxyWithNonce\",\"outputs\":[{\"internalType\":\"contract SafeProxy\",\"name\":\"proxy\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_singleton\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"initializer\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"saltNonce\",\"type\":\"uint256\"},{\"internalType\":\"contract IProxyCreationCallback\",\"name\":\"callback\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createProxyWithCallback\",\"outputs\":[{\"internalType\":\"contract SafeProxy\",\"name\":\"proxy\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_singleton\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"initializer\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"saltNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createProxyWithNonce\",\"outputs\":[{\"internalType\":\"contract SafeProxy\",\"name\":\"proxy\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"proxyCreationCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"createChainSpecificProxyWithNonce(address,bytes,uint256)\":{\"details\":\"Allows to create a new proxy contract that should exist only on 1 network (e.g. specific governance or admin accounts) by including the chain id in the create2 salt. Such proxies cannot be created on other networks by replaying the transaction.\",\"params\":{\"_singleton\":\"Address of singleton contract. Must be deployed at the time of execution.\",\"initializer\":\"Payload for a message call to be sent to a new proxy contract.\",\"saltNonce\":\"Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\"}},\"createProxyWithCallback(address,bytes,uint256,address)\":{\"params\":{\"_singleton\":\"Address of singleton contract. Must be deployed at the time of execution.\",\"callback\":\"Callback that will be invoked after the new proxy contract has been successfully deployed and initialized.\",\"initializer\":\"Payload for a message call to be sent to a new proxy contract.\",\"saltNonce\":\"Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\"}},\"createProxyWithNonce(address,bytes,uint256)\":{\"params\":{\"_singleton\":\"Address of singleton contract. Must be deployed at the time of execution.\",\"initializer\":\"Payload for a message call to be sent to a new proxy contract.\",\"saltNonce\":\"Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\"}},\"getChainId()\":{\"returns\":{\"_0\":\"The ID of the current chain as a uint256.\"}},\"proxyCreationCode()\":{\"details\":\"Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"createChainSpecificProxyWithNonce(address,bytes,uint256)\":{\"notice\":\"Deploys a new chain-specific proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy.\"},\"createProxyWithCallback(address,bytes,uint256,address)\":{\"notice\":\"Deploy a new proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy and calls a specified callback address `callback`.\"},\"createProxyWithNonce(address,bytes,uint256)\":{\"notice\":\"Deploys a new proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy.\"},\"getChainId()\":{\"notice\":\"Returns the ID of the chain the contract is currently deployed on.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"lib/safe-contracts/contracts/proxies/SafeProxyFactory.sol\":\"SafeProxyFactory\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/safe-contracts/contracts/proxies/IProxyCreationCallback.sol\":{\"keccak256\":\"0xf5410c842c1bbff96a2047b31f5437a9dc5183d004ab1fc9f952220f11379602\",\"urls\":[\"bzz-raw://0ac1fa0c7d6fc683384a3ce0b328c66adcc53b6a3e59d3b67c62404dd57c3099\",\"dweb:/ipfs/QmcVvxtcjZqyQwQcU4cPU4SZZ2LEahsmVWgJWGh5n8EHa7\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/proxies/SafeProxy.sol\":{\"keccak256\":\"0x5dccbe86285c1d4c4b2fed0ae8007620c3186d22411f43feecfbf8a028e5c7e2\",\"urls\":[\"bzz-raw://a1a02d01a92895110505e141d05b0924ea457a25b89a161f0aeedf6b5cb41aec\",\"dweb:/ipfs/QmYWEsFbWwtrVvEF9MNQtf4X3Qt13dAE8o44tEyAS9jmKP\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/proxies/SafeProxyFactory.sol\":{\"keccak256\":\"0xdc68ce6d07d02723fcdde9f115c976d78bc599667b4f9d08e6cda50f51949533\",\"urls\":[\"bzz-raw://0389c45311e383f0a27a928594341da67f061bf88795aafdbfb5e8449416fc26\",\"dweb:/ipfs/QmZXmXReN6uro3RAbh661G6LqfMEMeaLKRVoeJr5nx1tnh\"],\"license\":\"LGPL-3.0-only\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x189144bc1d2be6c69ab2d08b2dac14b1697accb8d2121b1c9a8a5d7e21c7296c", + "transactionIndex": "0x0", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x86fd3", + "gasUsed": "0x86fd3", + "contractAddress": "0x762C3f4f81a35fE4c224731dd0531CDA02fb2FE3", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x189144bc1d2be6c69ab2d08b2dac14b1697accb8d2121b1c9a8a5d7e21c7296c", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "createChainSpecificProxyWithNonce(address,bytes,uint256)": { + "notice": "Deploys a new chain-specific proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy." + }, + "createProxyWithCallback(address,bytes,uint256,address)": { + "notice": "Deploy a new proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy and calls a specified callback address `callback`." + }, + "createProxyWithNonce(address,bytes,uint256)": { + "notice": "Deploys a new proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy." + }, + "getChainId()": { + "notice": "Returns the ID of the chain the contract is currently deployed on." + } + } + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SafeSingleton.json b/e2e/deployments/devnetL1/SafeSingleton.json new file mode 100644 index 000000000000..5a3802214c50 --- /dev/null +++ b/e2e/deployments/devnetL1/SafeSingleton.json @@ -0,0 +1,1448 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "nonpayable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "VERSION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "addOwnerWithThreshold", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_threshold", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "approveHash", + "inputs": [ + { + "name": "hashToApprove", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "approvedHashes", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "changeThreshold", + "inputs": [ + { + "name": "_threshold", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "checkNSignatures", + "inputs": [ + { + "name": "dataHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "signatures", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "requiredSignatures", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "view" + }, + { + "type": "function", + "name": "checkSignatures", + "inputs": [ + { + "name": "dataHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "signatures", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "view" + }, + { + "type": "function", + "name": "disableModule", + "inputs": [ + { + "name": "prevModule", + "type": "address", + "internalType": "address" + }, + { + "name": "module", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "domainSeparator", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "enableModule", + "inputs": [ + { + "name": "module", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "encodeTransactionData", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "operation", + "type": "uint8", + "internalType": "enum Enum.Operation" + }, + { + "name": "safeTxGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "baseGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasToken", + "type": "address", + "internalType": "address" + }, + { + "name": "refundReceiver", + "type": "address", + "internalType": "address" + }, + { + "name": "_nonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "execTransaction", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "operation", + "type": "uint8", + "internalType": "enum Enum.Operation" + }, + { + "name": "safeTxGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "baseGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasToken", + "type": "address", + "internalType": "address" + }, + { + "name": "refundReceiver", + "type": "address", + "internalType": "address payable" + }, + { + "name": "signatures", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "success", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "execTransactionFromModule", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "operation", + "type": "uint8", + "internalType": "enum Enum.Operation" + } + ], + "outputs": [ + { + "name": "success", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "execTransactionFromModuleReturnData", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "operation", + "type": "uint8", + "internalType": "enum Enum.Operation" + } + ], + "outputs": [ + { + "name": "success", + "type": "bool", + "internalType": "bool" + }, + { + "name": "returnData", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getChainId", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getModulesPaginated", + "inputs": [ + { + "name": "start", + "type": "address", + "internalType": "address" + }, + { + "name": "pageSize", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "array", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "next", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getOwners", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getStorageAt", + "inputs": [ + { + "name": "offset", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "length", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getThreshold", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTransactionHash", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "operation", + "type": "uint8", + "internalType": "enum Enum.Operation" + }, + { + "name": "safeTxGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "baseGas", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "gasToken", + "type": "address", + "internalType": "address" + }, + { + "name": "refundReceiver", + "type": "address", + "internalType": "address" + }, + { + "name": "_nonce", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isModuleEnabled", + "inputs": [ + { + "name": "module", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "nonce", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeOwner", + "inputs": [ + { + "name": "prevOwner", + "type": "address", + "internalType": "address" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_threshold", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setFallbackHandler", + "inputs": [ + { + "name": "handler", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setGuard", + "inputs": [ + { + "name": "guard", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setup", + "inputs": [ + { + "name": "_owners", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "_threshold", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "fallbackHandler", + "type": "address", + "internalType": "address" + }, + { + "name": "paymentToken", + "type": "address", + "internalType": "address" + }, + { + "name": "payment", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "paymentReceiver", + "type": "address", + "internalType": "address payable" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "signedMessages", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "simulateAndRevert", + "inputs": [ + { + "name": "targetContract", + "type": "address", + "internalType": "address" + }, + { + "name": "calldataPayload", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "swapOwner", + "inputs": [ + { + "name": "prevOwner", + "type": "address", + "internalType": "address" + }, + { + "name": "oldOwner", + "type": "address", + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "AddedOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ApproveHash", + "inputs": [ + { + "name": "approvedHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ChangedFallbackHandler", + "inputs": [ + { + "name": "handler", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ChangedGuard", + "inputs": [ + { + "name": "guard", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ChangedThreshold", + "inputs": [ + { + "name": "threshold", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DisabledModule", + "inputs": [ + { + "name": "module", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "EnabledModule", + "inputs": [ + { + "name": "module", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ExecutionFailure", + "inputs": [ + { + "name": "txHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "payment", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ExecutionFromModuleFailure", + "inputs": [ + { + "name": "module", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ExecutionFromModuleSuccess", + "inputs": [ + { + "name": "module", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ExecutionSuccess", + "inputs": [ + { + "name": "txHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "payment", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RemovedOwner", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SafeReceived", + "inputs": [ + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SafeSetup", + "inputs": [ + { + "name": "initiator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "owners", + "type": "address[]", + "indexed": false, + "internalType": "address[]" + }, + { + "name": "threshold", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "initializer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "fallbackHandler", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SignMsg", + "inputs": [ + { + "name": "msgHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + } + ], + "address": "0x6c131727b94E8410600FE8B5A91cEa34b5B0e03c", + "args": [], + "bytecode": "0x608060405234801561001057600080fd5b506001600455614201806100256000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "author": "Stefan George - @Georgi87Richard Meissner - @rmeissner", + "details": "Most important concepts: - Threshold: Number of required confirmations for a Safe transaction. - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and approve transactions. Managed in `OwnerManager`. - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme. - Nonce: Each transaction should have a different nonce to prevent replay attacks. - Signature: A valid signature of an owner of the Safe for a transaction hash. - Guard: Guard is a contract that can execute pre- and post- transaction checks. Managed in `GuardManager`. - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`. - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`. Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/ For the events-based implementation see `SafeL2.sol`.", + "methods": { + "addOwnerWithThreshold(address,uint256)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "_threshold": "New threshold.", + "owner": "New owner address." + } + }, + "approveHash(bytes32)": { + "details": "This can be used with a pre-approved hash transaction signature. IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures", + "params": { + "hashToApprove": "The hash to mark as approved for signatures that are verified by this contract." + } + }, + "changeThreshold(uint256)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "_threshold": "New threshold." + } + }, + "checkNSignatures(bytes32,bytes,bytes,uint256)": { + "details": "Since the EIP-1271 does an external call, be mindful of reentrancy attacks.", + "params": { + "data": "That should be signed (this is passed to an external validator contract)", + "dataHash": "Hash of the data (could be either a message hash or transaction hash)", + "requiredSignatures": "Amount of required valid signatures.", + "signatures": "Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash." + } + }, + "checkSignatures(bytes32,bytes,bytes)": { + "params": { + "data": "That should be signed (this is passed to an external validator contract)", + "dataHash": "Hash of the data (could be either a message hash or transaction hash)", + "signatures": "Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash." + } + }, + "disableModule(address,address)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "module": "Module to be removed.", + "prevModule": "Previous module in the modules linked list." + } + }, + "domainSeparator()": { + "details": "Returns the domain separator for this contract, as defined in the EIP-712 standard.", + "returns": { + "_0": "bytes32 The domain separator hash." + } + }, + "enableModule(address)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "module": "Module to be whitelisted." + } + }, + "encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)": { + "params": { + "_nonce": "Transaction nonce.", + "baseGas": "Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)", + "data": "Data payload.", + "gasPrice": "Maximum gas price that should be used for this transaction.", + "gasToken": "Token address (or 0 if ETH) that is used for the payment.", + "operation": "Operation type.", + "refundReceiver": "Address of receiver of gas payment (or 0 if tx.origin).", + "safeTxGas": "Gas that should be used for the safe transaction.", + "to": "Destination address.", + "value": "Ether value." + }, + "returns": { + "_0": "Transaction hash bytes." + } + }, + "execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)": { + "details": "The fees are always transferred, even if the user transaction fails. This method doesn't perform any sanity check of the transaction, such as: - if the contract at `to` address has code or not - if the `gasToken` is a contract or not It is the responsibility of the caller to perform such checks.", + "params": { + "baseGas": "Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)", + "data": "Data payload of Safe transaction.", + "gasPrice": "Gas price that should be used for the payment calculation.", + "gasToken": "Token address (or 0 if ETH) that is used for the payment.", + "operation": "Operation type of Safe transaction.", + "refundReceiver": "Address of receiver of gas payment (or 0 if tx.origin).", + "safeTxGas": "Gas that should be used for the Safe transaction.", + "signatures": "Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash.", + "to": "Destination address of Safe transaction.", + "value": "Ether value of Safe transaction." + }, + "returns": { + "success": "Boolean indicating transaction's success." + } + }, + "execTransactionFromModule(address,uint256,bytes,uint8)": { + "details": "Function is virtual to allow overriding for L2 singleton to emit an event for indexing.", + "params": { + "data": "Data payload of module transaction.", + "operation": "Operation type of module transaction.", + "to": "Destination address of module transaction.", + "value": "Ether value of module transaction." + }, + "returns": { + "success": "Boolean flag indicating if the call succeeded." + } + }, + "execTransactionFromModuleReturnData(address,uint256,bytes,uint8)": { + "params": { + "data": "Data payload of module transaction.", + "operation": "Operation type of module transaction.", + "to": "Destination address of module transaction.", + "value": "Ether value of module transaction." + }, + "returns": { + "returnData": "Data returned by the call.", + "success": "Boolean flag indicating if the call succeeded." + } + }, + "getChainId()": { + "returns": { + "_0": "The ID of the current chain as a uint256." + } + }, + "getModulesPaginated(address,uint256)": { + "params": { + "pageSize": "Maximum number of modules that should be returned. Has to be > 0", + "start": "Start of the page. Has to be a module or start pointer (0x1 address)" + }, + "returns": { + "array": "Array of modules.", + "next": "Start of the next page." + } + }, + "getOwners()": { + "returns": { + "_0": "Array of Safe owners." + } + }, + "getStorageAt(uint256,uint256)": { + "params": { + "length": "- the number of words (32 bytes) of data to read", + "offset": "- the offset in the current contract's storage in words to start reading from" + }, + "returns": { + "_0": "the bytes that were read." + } + }, + "getThreshold()": { + "returns": { + "_0": "Threshold number." + } + }, + "getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)": { + "params": { + "_nonce": "Transaction nonce.", + "baseGas": "Gas costs for data used to trigger the safe transaction.", + "data": "Data payload.", + "gasPrice": "Maximum gas price that should be used for this transaction.", + "gasToken": "Token address (or 0 if ETH) that is used for the payment.", + "operation": "Operation type.", + "refundReceiver": "Address of receiver of gas payment (or 0 if tx.origin).", + "safeTxGas": "Fas that should be used for the safe transaction.", + "to": "Destination address.", + "value": "Ether value." + }, + "returns": { + "_0": "Transaction hash." + } + }, + "isModuleEnabled(address)": { + "returns": { + "_0": "True if the module is enabled" + } + }, + "isOwner(address)": { + "returns": { + "_0": "Boolean if owner is an owner of the Safe." + } + }, + "removeOwner(address,address,uint256)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "_threshold": "New threshold.", + "owner": "Owner address to be removed.", + "prevOwner": "Owner that pointed to the owner to be removed in the linked list" + } + }, + "setFallbackHandler(address)": { + "details": "Only fallback calls without value and with data will be forwarded. This can only be done via a Safe transaction. Cannot be set to the Safe itself.", + "params": { + "handler": "contract to handle fallback calls." + } + }, + "setGuard(address)": { + "details": "Set a guard that checks transactions before execution This can only be done via a Safe transaction. ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution, a broken guard can cause a denial of service for the Safe. Make sure to carefully audit the guard code and design recovery mechanisms.", + "params": { + "guard": "The address of the guard to be used or the 0 address to disable the guard" + } + }, + "setup(address[],uint256,address,bytes,address,address,uint256,address)": { + "details": "This method can only be called once. If a proxy was created without setting up, anyone can call setup and claim the proxy.", + "params": { + "_owners": "List of Safe owners.", + "_threshold": "Number of required confirmations for a Safe transaction.", + "data": "Data payload for optional delegate call.", + "fallbackHandler": "Handler for fallback calls to this contract", + "payment": "Value that should be paid", + "paymentReceiver": "Address that should receive the payment (or 0 if tx.origin)", + "paymentToken": "Token that should be used for the payment (0 is ETH)", + "to": "Contract address for optional delegate call." + } + }, + "simulateAndRevert(address,bytes)": { + "details": "Performs a delegatecall on a targetContract in the context of self. Internally reverts execution to avoid side effects (making it static). This method reverts with data equal to `abi.encode(bool(success), bytes(response))`. Specifically, the `returndata` after a call to this method will be: `success:bool || response.length:uint256 || response:bytes`.", + "params": { + "calldataPayload": "Calldata that should be sent to the target contract (encoded method name and arguments).", + "targetContract": "Address of the contract containing the code to execute." + } + }, + "swapOwner(address,address,address)": { + "details": "This can only be done via a Safe transaction.", + "params": { + "newOwner": "New owner address.", + "oldOwner": "Owner address to be replaced.", + "prevOwner": "Owner that pointed to the owner to be replaced in the linked list" + } + } + }, + "title": "Safe - A multisignature wallet with support for confirmations using signed messages based on EIP-712." + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"AddedOwner\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"approvedHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ApproveHash\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"handler\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ChangedFallbackHandler\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ChangedGuard\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ChangedThreshold\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"DisabledModule\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"EnabledModule\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ExecutionFailure\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ExecutionFromModuleFailure\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"ExecutionFromModuleSuccess\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ExecutionSuccess\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RemovedOwner\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SafeReceived\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initiator\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address[]\",\"name\":\"owners\",\"type\":\"address[]\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"initializer\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"fallbackHandler\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SafeSetup\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"SignMsg\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"addOwnerWithThreshold\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashToApprove\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"approveHash\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"approvedHashes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeThreshold\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signatures\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"requiredSignatures\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"checkNSignatures\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signatures\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"checkSignatures\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prevModule\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"disableModule\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"domainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"enableModule\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"enum Enum.Operation\",\"name\":\"operation\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"safeTxGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"gasToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundReceiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"encodeTransactionData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"enum Enum.Operation\",\"name\":\"operation\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"safeTxGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"gasToken\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"refundReceiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signatures\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"execTransaction\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"enum Enum.Operation\",\"name\":\"operation\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"execTransactionFromModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"enum Enum.Operation\",\"name\":\"operation\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"execTransactionFromModuleReturnData\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"start\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getModulesPaginated\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"array\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"next\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getOwners\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getStorageAt\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"enum Enum.Operation\",\"name\":\"operation\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"safeTxGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"gasToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundReceiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getTransactionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isModuleEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prevOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"removeOwner\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"handler\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setFallbackHandler\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGuard\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_owners\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"fallbackHandler\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"paymentReceiver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setup\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"signedMessages\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"targetContract\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"calldataPayload\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"simulateAndRevert\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prevOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"oldOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"swapOwner\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addOwnerWithThreshold(address,uint256)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"_threshold\":\"New threshold.\",\"owner\":\"New owner address.\"}},\"approveHash(bytes32)\":{\"details\":\"This can be used with a pre-approved hash transaction signature. IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures\",\"params\":{\"hashToApprove\":\"The hash to mark as approved for signatures that are verified by this contract.\"}},\"changeThreshold(uint256)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"_threshold\":\"New threshold.\"}},\"checkNSignatures(bytes32,bytes,bytes,uint256)\":{\"details\":\"Since the EIP-1271 does an external call, be mindful of reentrancy attacks.\",\"params\":{\"data\":\"That should be signed (this is passed to an external validator contract)\",\"dataHash\":\"Hash of the data (could be either a message hash or transaction hash)\",\"requiredSignatures\":\"Amount of required valid signatures.\",\"signatures\":\"Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash.\"}},\"checkSignatures(bytes32,bytes,bytes)\":{\"params\":{\"data\":\"That should be signed (this is passed to an external validator contract)\",\"dataHash\":\"Hash of the data (could be either a message hash or transaction hash)\",\"signatures\":\"Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash.\"}},\"disableModule(address,address)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"module\":\"Module to be removed.\",\"prevModule\":\"Previous module in the modules linked list.\"}},\"domainSeparator()\":{\"details\":\"Returns the domain separator for this contract, as defined in the EIP-712 standard.\",\"returns\":{\"_0\":\"bytes32 The domain separator hash.\"}},\"enableModule(address)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"module\":\"Module to be whitelisted.\"}},\"encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)\":{\"params\":{\"_nonce\":\"Transaction nonce.\",\"baseGas\":\"Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)\",\"data\":\"Data payload.\",\"gasPrice\":\"Maximum gas price that should be used for this transaction.\",\"gasToken\":\"Token address (or 0 if ETH) that is used for the payment.\",\"operation\":\"Operation type.\",\"refundReceiver\":\"Address of receiver of gas payment (or 0 if tx.origin).\",\"safeTxGas\":\"Gas that should be used for the safe transaction.\",\"to\":\"Destination address.\",\"value\":\"Ether value.\"},\"returns\":{\"_0\":\"Transaction hash bytes.\"}},\"execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)\":{\"details\":\"The fees are always transferred, even if the user transaction fails. This method doesn't perform any sanity check of the transaction, such as: - if the contract at `to` address has code or not - if the `gasToken` is a contract or not It is the responsibility of the caller to perform such checks.\",\"params\":{\"baseGas\":\"Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)\",\"data\":\"Data payload of Safe transaction.\",\"gasPrice\":\"Gas price that should be used for the payment calculation.\",\"gasToken\":\"Token address (or 0 if ETH) that is used for the payment.\",\"operation\":\"Operation type of Safe transaction.\",\"refundReceiver\":\"Address of receiver of gas payment (or 0 if tx.origin).\",\"safeTxGas\":\"Gas that should be used for the Safe transaction.\",\"signatures\":\"Signature data that should be verified. Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash.\",\"to\":\"Destination address of Safe transaction.\",\"value\":\"Ether value of Safe transaction.\"},\"returns\":{\"success\":\"Boolean indicating transaction's success.\"}},\"execTransactionFromModule(address,uint256,bytes,uint8)\":{\"details\":\"Function is virtual to allow overriding for L2 singleton to emit an event for indexing.\",\"params\":{\"data\":\"Data payload of module transaction.\",\"operation\":\"Operation type of module transaction.\",\"to\":\"Destination address of module transaction.\",\"value\":\"Ether value of module transaction.\"},\"returns\":{\"success\":\"Boolean flag indicating if the call succeeded.\"}},\"execTransactionFromModuleReturnData(address,uint256,bytes,uint8)\":{\"params\":{\"data\":\"Data payload of module transaction.\",\"operation\":\"Operation type of module transaction.\",\"to\":\"Destination address of module transaction.\",\"value\":\"Ether value of module transaction.\"},\"returns\":{\"returnData\":\"Data returned by the call.\",\"success\":\"Boolean flag indicating if the call succeeded.\"}},\"getChainId()\":{\"returns\":{\"_0\":\"The ID of the current chain as a uint256.\"}},\"getModulesPaginated(address,uint256)\":{\"params\":{\"pageSize\":\"Maximum number of modules that should be returned. Has to be > 0\",\"start\":\"Start of the page. Has to be a module or start pointer (0x1 address)\"},\"returns\":{\"array\":\"Array of modules.\",\"next\":\"Start of the next page.\"}},\"getOwners()\":{\"returns\":{\"_0\":\"Array of Safe owners.\"}},\"getStorageAt(uint256,uint256)\":{\"params\":{\"length\":\"- the number of words (32 bytes) of data to read\",\"offset\":\"- the offset in the current contract's storage in words to start reading from\"},\"returns\":{\"_0\":\"the bytes that were read.\"}},\"getThreshold()\":{\"returns\":{\"_0\":\"Threshold number.\"}},\"getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)\":{\"params\":{\"_nonce\":\"Transaction nonce.\",\"baseGas\":\"Gas costs for data used to trigger the safe transaction.\",\"data\":\"Data payload.\",\"gasPrice\":\"Maximum gas price that should be used for this transaction.\",\"gasToken\":\"Token address (or 0 if ETH) that is used for the payment.\",\"operation\":\"Operation type.\",\"refundReceiver\":\"Address of receiver of gas payment (or 0 if tx.origin).\",\"safeTxGas\":\"Fas that should be used for the safe transaction.\",\"to\":\"Destination address.\",\"value\":\"Ether value.\"},\"returns\":{\"_0\":\"Transaction hash.\"}},\"isModuleEnabled(address)\":{\"returns\":{\"_0\":\"True if the module is enabled\"}},\"isOwner(address)\":{\"returns\":{\"_0\":\"Boolean if owner is an owner of the Safe.\"}},\"removeOwner(address,address,uint256)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"_threshold\":\"New threshold.\",\"owner\":\"Owner address to be removed.\",\"prevOwner\":\"Owner that pointed to the owner to be removed in the linked list\"}},\"setFallbackHandler(address)\":{\"details\":\"Only fallback calls without value and with data will be forwarded. This can only be done via a Safe transaction. Cannot be set to the Safe itself.\",\"params\":{\"handler\":\"contract to handle fallback calls.\"}},\"setGuard(address)\":{\"details\":\"Set a guard that checks transactions before execution This can only be done via a Safe transaction. ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution, a broken guard can cause a denial of service for the Safe. Make sure to carefully audit the guard code and design recovery mechanisms.\",\"params\":{\"guard\":\"The address of the guard to be used or the 0 address to disable the guard\"}},\"setup(address[],uint256,address,bytes,address,address,uint256,address)\":{\"details\":\"This method can only be called once. If a proxy was created without setting up, anyone can call setup and claim the proxy.\",\"params\":{\"_owners\":\"List of Safe owners.\",\"_threshold\":\"Number of required confirmations for a Safe transaction.\",\"data\":\"Data payload for optional delegate call.\",\"fallbackHandler\":\"Handler for fallback calls to this contract\",\"payment\":\"Value that should be paid\",\"paymentReceiver\":\"Address that should receive the payment (or 0 if tx.origin)\",\"paymentToken\":\"Token that should be used for the payment (0 is ETH)\",\"to\":\"Contract address for optional delegate call.\"}},\"simulateAndRevert(address,bytes)\":{\"details\":\"Performs a delegatecall on a targetContract in the context of self. Internally reverts execution to avoid side effects (making it static). This method reverts with data equal to `abi.encode(bool(success), bytes(response))`. Specifically, the `returndata` after a call to this method will be: `success:bool || response.length:uint256 || response:bytes`.\",\"params\":{\"calldataPayload\":\"Calldata that should be sent to the target contract (encoded method name and arguments).\",\"targetContract\":\"Address of the contract containing the code to execute.\"}},\"swapOwner(address,address,address)\":{\"details\":\"This can only be done via a Safe transaction.\",\"params\":{\"newOwner\":\"New owner address.\",\"oldOwner\":\"Owner address to be replaced.\",\"prevOwner\":\"Owner that pointed to the owner to be replaced in the linked list\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addOwnerWithThreshold(address,uint256)\":{\"notice\":\"Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.\"},\"approveHash(bytes32)\":{\"notice\":\"Marks hash `hashToApprove` as approved.\"},\"changeThreshold(uint256)\":{\"notice\":\"Changes the threshold of the Safe to `_threshold`.\"},\"checkNSignatures(bytes32,bytes,bytes,uint256)\":{\"notice\":\"Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise.\"},\"checkSignatures(bytes32,bytes,bytes)\":{\"notice\":\"Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise.\"},\"disableModule(address,address)\":{\"notice\":\"Disables the module `module` for the Safe.\"},\"enableModule(address)\":{\"notice\":\"Enables the module `module` for the Safe.\"},\"encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)\":{\"notice\":\"Returns the pre-image of the transaction hash (see getTransactionHash).\"},\"execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)\":{\"notice\":\"Executes a `operation` {0: Call, 1: DelegateCall}} transaction to `to` with `value` (Native Currency) and pays `gasPrice` * `gasLimit` in `gasToken` token to `refundReceiver`.\"},\"execTransactionFromModule(address,uint256,bytes,uint8)\":{\"notice\":\"Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token)\"},\"execTransactionFromModuleReturnData(address,uint256,bytes,uint8)\":{\"notice\":\"Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) and return data\"},\"getChainId()\":{\"notice\":\"Returns the ID of the chain the contract is currently deployed on.\"},\"getModulesPaginated(address,uint256)\":{\"notice\":\"Returns an array of modules. If all entries fit into a single page, the next pointer will be 0x1. If another page is present, next will be the last element of the returned array.\"},\"getOwners()\":{\"notice\":\"Returns a list of Safe owners.\"},\"getStorageAt(uint256,uint256)\":{\"notice\":\"Reads `length` bytes of storage in the currents contract\"},\"getThreshold()\":{\"notice\":\"Returns the number of required confirmations for a Safe transaction aka the threshold.\"},\"getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)\":{\"notice\":\"Returns transaction hash to be signed by owners.\"},\"isModuleEnabled(address)\":{\"notice\":\"Returns if an module is enabled\"},\"isOwner(address)\":{\"notice\":\"Returns if `owner` is an owner of the Safe.\"},\"removeOwner(address,address,uint256)\":{\"notice\":\"Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.\"},\"setFallbackHandler(address)\":{\"notice\":\"Set Fallback Handler to `handler` for the Safe.\"},\"setGuard(address)\":{\"notice\":\"Set Transaction Guard `guard` for the Safe. Make sure you trust the guard.\"},\"setup(address[],uint256,address,bytes,address,address,uint256,address)\":{\"notice\":\"Sets an initial storage of the Safe contract.\"},\"swapOwner(address,address,address)\":{\"notice\":\"Replaces the owner `oldOwner` in the Safe with `newOwner`.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"lib/safe-contracts/contracts/Safe.sol\":\"Safe\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/safe-contracts/contracts/Safe.sol\":{\"keccak256\":\"0xfe09ad8ce3359ee997c4127c14264a94ec6f25dea38dc37997bd705e9aed9fcd\",\"urls\":[\"bzz-raw://434e77c4ace5cefcf5a21af7eceb5b60ca45b55818e1ecf938d196345731c5e9\",\"dweb:/ipfs/QmbYFyE4okvruZZuCxeNy86Hm6W7yPR4yJWkVztbPRTosu\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/base/Executor.sol\":{\"keccak256\":\"0xf0be832e7529e92000544170a5529d73666a9b5e836b30c6f2ed6ef7d7d8c94a\",\"urls\":[\"bzz-raw://710022b40c9f78a5b55b97f6ce600e4834df2ddd36bf714974d953883c82d58c\",\"dweb:/ipfs/QmbdJNKH5opevm7HxQKQAe6W7dQTgSHKa4nKvbUNGRcQQp\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/base/FallbackManager.sol\":{\"keccak256\":\"0x646b3088f15af8b4f71ac5eeffaa24ce0c1abed5f494f90368208b09e35d5165\",\"urls\":[\"bzz-raw://7975be46d228510c70659b18076aecb3b0e7331b4d3a162444304145143bdc6e\",\"dweb:/ipfs/QmRRbZrWUnoky6pVo8zMUzCTsshR4sZ2FjR13s8vyAb8dV\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/base/GuardManager.sol\":{\"keccak256\":\"0xedfc7c830ab35e52d1208986b253f3422c2f0ca68054c10819fb348fcc6ccf5d\",\"urls\":[\"bzz-raw://3ff8a4194d1160d2e23142937bc9d7eac7b6b553b1ee226390a0df07ebac1b64\",\"dweb:/ipfs/QmSw8Y7z4TQrUTEosdWqcug7TUv9Tg1kxqMKHd7RuTnyzx\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/base/ModuleManager.sol\":{\"keccak256\":\"0xd929f3cd77ab05904d7ad510d25e79a84172728c6e6f887872d7d5176ed2ada7\",\"urls\":[\"bzz-raw://f9c3ae921990787102f8ff6e9d55b3329b6fed6b0e67ea4c8e225b53378359df\",\"dweb:/ipfs/QmbDTmeBsNLXRrM1n8jT9qEnNcNv2G3SQY7NV7kex9EtLh\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/base/OwnerManager.sol\":{\"keccak256\":\"0xec9799093eb7a73461cd5e563198751ee222f956f754ea622a03fe953e515b2c\",\"urls\":[\"bzz-raw://5729c58b14e7b656c71dd3377e9519c0d34ef8c04851a9a21c3d62393e4fae7a\",\"dweb:/ipfs/QmRRtfFpNqvdANny9TYBr8rA3HbT1egUCpb2uXALMHkVxK\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/Enum.sol\":{\"keccak256\":\"0x4ff3008926a118e9f36e6747facc39dd13168e0d00f516888ae966ec20766453\",\"urls\":[\"bzz-raw://385929800d1c0f92eb165fcf37a9e28b395b17d8b74f74755654d3a096a0fc34\",\"dweb:/ipfs/QmagieLuN2jrp2oJHFyZuyz65Sh1CcupnXSEKypGFS5Gvo\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/NativeCurrencyPaymentFallback.sol\":{\"keccak256\":\"0x3ddcd4130c67326033dcf773d2d87d7147e3a8386993ea3ab3f1c38da406adba\",\"urls\":[\"bzz-raw://740a729397b6a0d903f4738a50e856d4e5039555024937b148d97529525dbfa9\",\"dweb:/ipfs/QmQJuNVvHbkeJ6jjd75D8FsZBPXH6neoGBZdQgtsA82E7g\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/SecuredTokenTransfer.sol\":{\"keccak256\":\"0x1eb8c3601538b73dd6a823ac4fca49bb8adc97d1302a936622156636c971eb05\",\"urls\":[\"bzz-raw://c26495b1fe9229ea17f90b70f295030880d629b9ea3016ea20b634983865f7b3\",\"dweb:/ipfs/QmTc1UmKcynkKn8DeviLMuy6scxNvAVSdLoX4ndUtdEL9N\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/SelfAuthorized.sol\":{\"keccak256\":\"0xfb0e176bb208e047a234fe757e2acd13787e27879570b8544547ac787feb5f13\",\"urls\":[\"bzz-raw://8e9a317f0c3c02ab1d6c38039bff2b3e0c97f4dc9d229d3d9149c1af1c5023b3\",\"dweb:/ipfs/QmNcZjNChsuXF34T6f3Zu7i3tnqvKN4NyWBWZ4tXLH9kMu\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/SignatureDecoder.sol\":{\"keccak256\":\"0x2a3baf0efa1585ddf2276505c6d34fa16f01cafff1288e40110d5e67fb459c7c\",\"urls\":[\"bzz-raw://00cdded3068b9051ee0a966f40926fbc57dbe7ef8bf4285db3740f9d50468c80\",\"dweb:/ipfs/QmcP5hKmaRqBe7TpgoXtncZqsNKKdCCKxZgXoxEL4Nj5F4\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/Singleton.sol\":{\"keccak256\":\"0xcab7c6e5fb6d7295a9343f72fec26a2f632ddfe220a6f267b5c5a1eb2f9bce50\",\"urls\":[\"bzz-raw://dd1c31d5787ef590a60f6b0dbc74d09e6fe4d3ad2f0529940d662bf315521cde\",\"dweb:/ipfs/QmSAS5DYrGksJe4cPQ4wLrveXa1CjxAuEiohcLpPG5h2bo\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/common/StorageAccessible.sol\":{\"keccak256\":\"0x2c5412a8f014db332322a6b24ee3cedce15dca17a721ae49fdef368568d4391e\",\"urls\":[\"bzz-raw://e775f267d3e60ebe452d9533f46a0eb1f1dc4593d1bcb553e86cea205a5f361e\",\"dweb:/ipfs/QmQdYDHGQsiMx1AADWRhX7tduU9ycTzrT5q3zBWvphXzKZ\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/external/SafeMath.sol\":{\"keccak256\":\"0x5f856674d9be11344c5899deb43364e19baa75bc881cada4c159938270b2bd89\",\"urls\":[\"bzz-raw://351c66e5fe92c0a51f79d133521545dabdd3f756312a7b1428c1fc813c512a1c\",\"dweb:/ipfs/QmdnrRmgef8SdamEU6fVEqFD5RQwXeDFTfQuZEfX2vxC4x\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x779ed3893a8812e383670b755f65c7727e9343dadaa4d7a4aa7f4aa35d859fdb\",\"urls\":[\"bzz-raw://bb2039e1459ace1e68761e873632fc339866332f9f5ecb7452a0bc3a3b847e89\",\"dweb:/ipfs/QmYXvDQXJnDkXFvsvKLyZXaAv4x42qvtbtmwHftP4RKX38\"],\"license\":\"LGPL-3.0-only\"},\"lib/safe-contracts/contracts/interfaces/ISignatureValidator.sol\":{\"keccak256\":\"0x2459cb3ed73ecb80e1e7a6508d09a58cc59570b049f77042f669dedfcc5f6457\",\"urls\":[\"bzz-raw://3c4a1371948b11f78171bc4ae4fd169a1eec11e5c4b273eb2c54bc030a1aae25\",\"dweb:/ipfs/QmPuztatXZYVS65n8YbCyccJFZYPP6zQfBQ8tTY27pB978\"],\"license\":\"LGPL-3.0-only\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x2749b5b51f6d32df730cd8a873d5e3a551638d5d537b9ad21f78d12235b0ee18", + "transactionIndex": "0x1", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x40c068", + "gasUsed": "0x385095", + "contractAddress": "0x6c131727b94E8410600FE8B5A91cEa34b5B0e03c", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 57485, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "singleton", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 56478, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "modules", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 56893, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "owners", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 56895, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "ownerCount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 56897, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "threshold", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 55386, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "nonce", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 55388, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "_deprecatedDomainSeparator", + "offset": 0, + "slot": "6", + "type": "t_bytes32" + }, + { + "astId": 55392, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "signedMessages", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_bytes32,t_uint256)" + }, + { + "astId": 55398, + "contract": "lib/safe-contracts/contracts/Safe.sol:Safe", + "label": "approvedHashes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bytes32 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_uint256)" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0x2749b5b51f6d32df730cd8a873d5e3a551638d5d537b9ad21f78d12235b0ee18", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "addOwnerWithThreshold(address,uint256)": { + "notice": "Adds the owner `owner` to the Safe and updates the threshold to `_threshold`." + }, + "approveHash(bytes32)": { + "notice": "Marks hash `hashToApprove` as approved." + }, + "changeThreshold(uint256)": { + "notice": "Changes the threshold of the Safe to `_threshold`." + }, + "checkNSignatures(bytes32,bytes,bytes,uint256)": { + "notice": "Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise." + }, + "checkSignatures(bytes32,bytes,bytes)": { + "notice": "Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise." + }, + "disableModule(address,address)": { + "notice": "Disables the module `module` for the Safe." + }, + "enableModule(address)": { + "notice": "Enables the module `module` for the Safe." + }, + "encodeTransactionData(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)": { + "notice": "Returns the pre-image of the transaction hash (see getTransactionHash)." + }, + "execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)": { + "notice": "Executes a `operation` {0: Call, 1: DelegateCall}} transaction to `to` with `value` (Native Currency) and pays `gasPrice` * `gasLimit` in `gasToken` token to `refundReceiver`." + }, + "execTransactionFromModule(address,uint256,bytes,uint8)": { + "notice": "Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token)" + }, + "execTransactionFromModuleReturnData(address,uint256,bytes,uint8)": { + "notice": "Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) and return data" + }, + "getChainId()": { + "notice": "Returns the ID of the chain the contract is currently deployed on." + }, + "getModulesPaginated(address,uint256)": { + "notice": "Returns an array of modules. If all entries fit into a single page, the next pointer will be 0x1. If another page is present, next will be the last element of the returned array." + }, + "getOwners()": { + "notice": "Returns a list of Safe owners." + }, + "getStorageAt(uint256,uint256)": { + "notice": "Reads `length` bytes of storage in the currents contract" + }, + "getThreshold()": { + "notice": "Returns the number of required confirmations for a Safe transaction aka the threshold." + }, + "getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)": { + "notice": "Returns transaction hash to be signed by owners." + }, + "isModuleEnabled(address)": { + "notice": "Returns if an module is enabled" + }, + "isOwner(address)": { + "notice": "Returns if `owner` is an owner of the Safe." + }, + "removeOwner(address,address,uint256)": { + "notice": "Removes the owner `owner` from the Safe and updates the threshold to `_threshold`." + }, + "setFallbackHandler(address)": { + "notice": "Set Fallback Handler to `handler` for the Safe." + }, + "setGuard(address)": { + "notice": "Set Transaction Guard `guard` for the Safe. Make sure you trust the guard." + }, + "setup(address[],uint256,address,bytes,address,address,uint256,address)": { + "notice": "Sets an initial storage of the Safe contract." + }, + "swapOwner(address,address,address)": { + "notice": "Replaces the owner `oldOwner` in the Safe with `newOwner`." + } + } + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SuperchainConfig.json b/e2e/deployments/devnetL1/SuperchainConfig.json new file mode 100644 index 000000000000..71d3a0bd44ea --- /dev/null +++ b/e2e/deployments/devnetL1/SuperchainConfig.json @@ -0,0 +1,280 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "GUARDIAN_SLOT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PAUSED_SLOT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "guardian", + "inputs": [], + "outputs": [ + { + "name": "guardian_", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_guardian", + "type": "address", + "internalType": "address" + }, + { + "name": "_paused", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "pause", + "inputs": [ + { + "name": "_identifier", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "paused_", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "unpause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ConfigUpdate", + "inputs": [ + { + "name": "updateType", + "type": "uint8", + "indexed": true, + "internalType": "enum SuperchainConfig.UpdateType" + }, + { + "name": "data", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [ + { + "name": "identifier", + "type": "string", + "indexed": false, + "internalType": "string" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Unpaused", + "inputs": [], + "anonymous": false + } + ], + "address": "0x068E44eB31e111028c41598E4535be7468674D0A", + "args": [], + "bytecode": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000361565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200019460201b620005fd1760201c565b15801562000076575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010d83620001a3565b81156200014857604080518082019091526012815271125b9a5d1a585b1a5e995c881c185d5cd95960721b6020820152620001489062000248565b80156200018f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b620001e9620001d460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69620002cf565b60001b82620002cb60201b620006191760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526200023d9162000345565b60405180910390a250565b6200028f6200027960017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7620002cf565b60001b6001620002cb60201b620006191760201c565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea2838181604051620002c0919062000345565b60405180910390a150565b9055565b600082821015620002f057634e487b7160e01b600052601160045260246000fd5b500390565b6000815180845260005b818110156200031d57602081850181015186830182015201620002ff565b8181111562000330576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006200035a6020830184620002f5565b9392505050565b61096b80620003716000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "initialize(address,bool)": { + "params": { + "_guardian": "Address of the guardian, can pause the OptimismPortal.", + "_paused": "Initial paused status." + } + }, + "pause(string)": { + "params": { + "_identifier": "(Optional) A string to identify provenance of the pause transaction." + } + } + }, + "events": { + "ConfigUpdate(uint8,bytes)": { + "params": { + "data": "Encoded update data.", + "updateType": "Type of update." + } + }, + "Paused(string)": { + "params": { + "identifier": "A string helping to identify provenance of the pause transaction." + } + } + }, + "title": "SuperchainConfig" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"enum SuperchainConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PAUSED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"guardian_\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_identifier\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"pause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"unpause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,bool)\":{\"params\":{\"_guardian\":\"Address of the guardian, can pause the OptimismPortal.\",\"_paused\":\"Initial paused status.\"}},\"pause(string)\":{\"params\":{\"_identifier\":\"(Optional) A string to identify provenance of the pause transaction.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN_SLOT()\":{\"notice\":\"The address of the guardian, which can pause withdrawals from the System. It can only be modified by an upgrade.\"},\"PAUSED_SLOT()\":{\"notice\":\"Whether or not the Superchain is paused.\"},\"constructor\":{\"notice\":\"Constructs the SuperchainConfig contract.\"},\"guardian()\":{\"notice\":\"Getter for the guardian address.\"},\"initialize(address,bool)\":{\"notice\":\"Initializer.\"},\"pause(string)\":{\"notice\":\"Pauses withdrawals.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"unpause()\":{\"notice\":\"Unpauses withdrawals.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SuperchainConfig.sol\":\"SuperchainConfig\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 47332, + "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 47335, + "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x4d07a5d3574e88e97c9e319fd3f7dcf950d1ac330475b31fa81d6485ea8ff8ed", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "GUARDIAN_SLOT()": { + "notice": "The address of the guardian, which can pause withdrawals from the System. It can only be modified by an upgrade." + }, + "PAUSED_SLOT()": { + "notice": "Whether or not the Superchain is paused." + }, + "constructor": { + "notice": "Constructs the SuperchainConfig contract." + }, + "guardian()": { + "notice": "Getter for the guardian address." + }, + "initialize(address,bool)": { + "notice": "Initializer." + }, + "pause(string)": { + "notice": "Pauses withdrawals." + }, + "paused()": { + "notice": "Getter for the current paused status." + }, + "unpause()": { + "notice": "Unpauses withdrawals." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ConfigUpdate(uint8,bytes)": { + "notice": "Emitted when configuration is updated." + }, + "Paused(string)": { + "notice": "Emitted when the pause is triggered." + }, + "Unpaused()": { + "notice": "Emitted when the pause is lifted." + } + }, + "notice": "The SuperchainConfig contract is used to manage configuration of global superchain values." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SuperchainConfigProxy.json b/e2e/deployments/devnetL1/SuperchainConfigProxy.json new file mode 100644 index 000000000000..820d6a9930a7 --- /dev/null +++ b/e2e/deployments/devnetL1/SuperchainConfigProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x0875bb7930651b28557c4fe0944cfd64cfaE033b", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0xf2f5e496104a43aa55b7ab2858b1472d5f3ecebcb3a6a16625b493cc85385835", + "transactionIndex": "0x7", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x6a2a1b", + "gasUsed": "0x80250", + "contractAddress": "0x0875bb7930651b28557c4fe0944cfd64cfaE033b", + "logs": [ + { + "address": "0x0875bb7930651b28557c4fe0944cfd64cfaE033b", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0xf2f5e496104a43aa55b7ab2858b1472d5f3ecebcb3a6a16625b493cc85385835", + "transactionIndex": "0x7", + "logIndex": "0x6", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000010000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0xf2f5e496104a43aa55b7ab2858b1472d5f3ecebcb3a6a16625b493cc85385835", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SystemConfig.json b/e2e/deployments/devnetL1/SystemConfig.json new file mode 100644 index 000000000000..aa53e7026758 --- /dev/null +++ b/e2e/deployments/devnetL1/SystemConfig.json @@ -0,0 +1,986 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_overhead", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_scalar", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_batcherHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_gasLimit", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "_unsafeBlockSigner", + "type": "address", + "internalType": "address" + }, + { + "name": "_config", + "type": "tuple", + "internalType": "struct ResourceMetering.ResourceConfig", + "components": [ + { + "name": "maxResourceLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "elasticityMultiplier", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "baseFeeMaxChangeDenominator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minimumBaseFee", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "systemTxMaxGas", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "maximumBaseFee", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "UNSAFE_BLOCK_SIGNER_SLOT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "VERSION", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "batcherHash", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "gasLimit", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "_owner", + "type": "address", + "internalType": "address" + }, + { + "name": "_overhead", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_scalar", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_batcherHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_gasLimit", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "_unsafeBlockSigner", + "type": "address", + "internalType": "address" + }, + { + "name": "_config", + "type": "tuple", + "internalType": "struct ResourceMetering.ResourceConfig", + "components": [ + { + "name": "maxResourceLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "elasticityMultiplier", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "baseFeeMaxChangeDenominator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minimumBaseFee", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "systemTxMaxGas", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "maximumBaseFee", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "minimumGasLimit", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "overhead", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "resourceConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ResourceMetering.ResourceConfig", + "components": [ + { + "name": "maxResourceLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "elasticityMultiplier", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "baseFeeMaxChangeDenominator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minimumBaseFee", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "systemTxMaxGas", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "maximumBaseFee", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "scalar", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "setBatcherHash", + "inputs": [ + { + "name": "_batcherHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setGasConfig", + "inputs": [ + { + "name": "_overhead", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_scalar", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setGasLimit", + "inputs": [ + { + "name": "_gasLimit", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setResourceConfig", + "inputs": [ + { + "name": "_config", + "type": "tuple", + "internalType": "struct ResourceMetering.ResourceConfig", + "components": [ + { + "name": "maxResourceLimit", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "elasticityMultiplier", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "baseFeeMaxChangeDenominator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "minimumBaseFee", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "systemTxMaxGas", + "type": "uint32", + "internalType": "uint32" + }, + { + "name": "maximumBaseFee", + "type": "uint128", + "internalType": "uint128" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setUnsafeBlockSigner", + "inputs": [ + { + "name": "_unsafeBlockSigner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "unsafeBlockSigner", + "inputs": [], + "outputs": [ + { + "name": "addr_", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ConfigUpdate", + "inputs": [ + { + "name": "version", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "updateType", + "type": "uint8", + "indexed": true, + "internalType": "enum SystemConfig.UpdateType" + }, + { + "name": "data", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "args": [ + "0x000000000000000000000000000000000000dEaD", + "0", + "0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "21000000", + "0x0000000000000000000000000000000000000000", + "(20000000, 10, 8, 1000000000, 1000000, 340282366920938463463374607431768211455)" + ], + "bytecode": "0x60806040523480156200001157600080fd5b5060405162002187380380620021878339810160408190526200003491620009c1565b620000458787878787878762000052565b5050505050505062000c19565b600054610100900460ff1615808015620000735750600054600160ff909116105b80620000a3575062000090306200022a60201b620008131760201c565b158015620000a3575060005460ff166001145b6200010c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000130576000805461ff0019166101001790555b6200013a62000239565b6200014588620002a1565b620001508562000320565b6200015c878762000372565b6200016784620003d6565b620001728362000473565b6200017d82620004db565b620001876200081f565b6001600160401b0316846001600160401b03161015620001d95760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b801562000220576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002955760405162461bcd60e51b815260206004820152602b60248201526000805160206200216783398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000103565b6200029f6200084c565b565b620002ab620008b3565b6001600160a01b038116620003125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000103565b6200031d816200090f565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b6000600080516020620021478339815191528360405162000366919062000afa565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f198184030181529190529050600160006000805160206200214783398151915283604051620003c9919062000afa565b60405180910390a3505050565b620003e06200081f565b6001600160401b0316816001600160401b03161015620004325760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000344565b620004aa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08826200096160201b6200082f1760201c565b604080516001600160a01b03831660208201526000910160408051601f198184030181529190529050600362000344565b8060a001516001600160801b0316816060015163ffffffff1611156200056a5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000103565b6001816040015160ff1611620005db5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000103565b606854608082015182516001600160401b0390921691620005fd919062000b68565b63ffffffff161115620006425760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b6000816020015160ff1611620006b35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000103565b8051602082015163ffffffff82169160ff90911690620006d590829062000b93565b620006e1919062000bc5565b63ffffffff16146200075c5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000103565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b606954600090620008479063ffffffff6a010000000000000000000082048116911662000bf4565b905090565b600054610100900460ff16620008a85760405162461bcd60e51b815260206004820152602b60248201526000805160206200216783398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000103565b6200029f336200090f565b6033546001600160a01b031633146200029f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000103565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b80516001600160a01b03811681146200097d57600080fd5b919050565b805163ffffffff811681146200097d57600080fd5b805160ff811681146200097d57600080fd5b80516001600160801b03811681146200097d57600080fd5b6000806000806000806000878903610180811215620009df57600080fd5b620009ea8962000965565b60208a015160408b015160608c015160808d0151939b50919950975095506001600160401b03808216821462000a1f57600080fd5b81955062000a3060a08c0162000965565b945060c060bf198401121562000a4557600080fd5b604051925060c083019150828210818311171562000a7357634e487b7160e01b600052604160045260246000fd5b5060405262000a8560c08a0162000982565b815262000a9560e08a0162000997565b602082015262000aa96101008a0162000997565b604082015262000abd6101208a0162000982565b606082015262000ad16101408a0162000982565b608082015262000ae56101608a01620009a9565b60a08201528091505092959891949750929550565b600060208083528351808285015260005b8181101562000b295785810183015185820160400152820162000b0b565b8181111562000b3c576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff80831681851680830382111562000b8a5762000b8a62000b52565b01949350505050565b600063ffffffff8084168062000bb957634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000beb5762000beb62000b52565b02949350505050565b60006001600160401b0382811684821680830382111562000b8a5762000b8a62000b52565b6114fe8062000c296000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b714610410578063f975e92514610424578063ffa1ad741461043757600080fd5b8063f2fde38b146103f4578063f45e65d81461040757600080fd5b8063c9b26f61116100b2578063c9b26f61146102a4578063cc731b02146102b7578063e81b2c6d146103eb57600080fd5b8063b40a817c1461027e578063c71973f61461029157600080fd5b80634f16540b11610124578063715018a611610109578063715018a6146102455780638da5cb5b1461024d578063935f029e1461026b57600080fd5b80634f16540b146101d557806354fd4d50146101fc57600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101b4575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611156565b61043f565b005b61018f610453565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101bc610482565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6102386040518060400160405280600681526020017f312e31312e30000000000000000000000000000000000000000000000000000081525081565b60405161016991906111e3565b6101856104a8565b60335473ffffffffffffffffffffffffffffffffffffffff1661018f565b6101856102793660046111f6565b6104bc565b61018561028c366004611230565b6104d2565b61018561029f366004611359565b6104e3565b6101856102b2366004611375565b6104f4565b61037b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b610185610402366004611156565b610505565b61015f60665481565b6068546101bc9067ffffffffffffffff1681565b61018561043236600461138e565b6105be565b61015f600081565b610447610833565b610450816108b4565b50565b600061047d7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b905090565b60695460009061047d9063ffffffff6a0100000000000000000000820481169116611430565b6104b0610833565b6104ba6000610971565b565b6104c4610833565b6104ce82826109e8565b5050565b6104da610833565b61045081610a79565b6104eb610833565b61045081610b57565b6104fc610833565b61045081610fcb565b61050d610833565b73ffffffffffffffffffffffffffffffffffffffff81166105b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61045081610971565b600054610100900460ff16158080156105de5750600054600160ff909116105b806105f85750303b1580156105f8575060005460ff166001145b610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105ac565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106e257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6106ea610ff3565b6106f388610505565b6106fc85610fcb565b61070687876109e8565b61070f84610a79565b610718836108b4565b61072182610b57565b610729610482565b67ffffffffffffffff168467ffffffffffffffff1610156107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b801561080957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b6108dd7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161096591906111e3565b60405180910390a35050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610a6c91906111e3565b60405180910390a3505050565b610a81610482565b67ffffffffffffffff168167ffffffffffffffff161015610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610934565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610c07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016105ac565b6001816040015160ff1611610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016105ac565b6068546080820151825167ffffffffffffffff90921691610cbf919061145c565b63ffffffff161115610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b6000816020015160ff1611610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016105ac565b8051602082015163ffffffff82169160ff90911690610de490829061147b565b610dee91906114c5565b63ffffffff1614610e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016105ac565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6067819055604080516020808201849052825180830390910181529082019091526000610934565b600054610100900460ff1661108a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba600054610100900460ff16611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba33610971565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115157600080fd5b919050565b60006020828403121561116857600080fd5b6111718261112d565b9392505050565b6000815180845260005b8181101561119e57602081850181015186830182015201611182565b818111156111b0576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111716020830184611178565b6000806040838503121561120957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461115157600080fd5b60006020828403121561124257600080fd5b61117182611218565b803563ffffffff8116811461115157600080fd5b803560ff8116811461115157600080fd5b80356fffffffffffffffffffffffffffffffff8116811461115157600080fd5b600060c082840312156112a257600080fd5b60405160c0810181811067ffffffffffffffff821117156112ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806112fb8361124b565b81526113096020840161125f565b602082015261131a6040840161125f565b604082015261132b6060840161124b565b606082015261133c6080840161124b565b608082015261134d60a08401611270565b60a08201525092915050565b600060c0828403121561136b57600080fd5b6111718383611290565b60006020828403121561138757600080fd5b5035919050565b6000806000806000806000610180888a0312156113aa57600080fd5b6113b38861112d565b96506020880135955060408801359450606088013593506113d660808901611218565b92506113e460a0890161112d565b91506113f38960c08a01611290565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561145357611453611401565b01949350505050565b600063ffffffff80831681851680830382111561145357611453611401565b600063ffffffff808416806114b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156114e8576114e8611401565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b714610410578063f975e92514610424578063ffa1ad741461043757600080fd5b8063f2fde38b146103f4578063f45e65d81461040757600080fd5b8063c9b26f61116100b2578063c9b26f61146102a4578063cc731b02146102b7578063e81b2c6d146103eb57600080fd5b8063b40a817c1461027e578063c71973f61461029157600080fd5b80634f16540b11610124578063715018a611610109578063715018a6146102455780638da5cb5b1461024d578063935f029e1461026b57600080fd5b80634f16540b146101d557806354fd4d50146101fc57600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101b4575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611156565b61043f565b005b61018f610453565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101bc610482565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6102386040518060400160405280600681526020017f312e31312e30000000000000000000000000000000000000000000000000000081525081565b60405161016991906111e3565b6101856104a8565b60335473ffffffffffffffffffffffffffffffffffffffff1661018f565b6101856102793660046111f6565b6104bc565b61018561028c366004611230565b6104d2565b61018561029f366004611359565b6104e3565b6101856102b2366004611375565b6104f4565b61037b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b610185610402366004611156565b610505565b61015f60665481565b6068546101bc9067ffffffffffffffff1681565b61018561043236600461138e565b6105be565b61015f600081565b610447610833565b610450816108b4565b50565b600061047d7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b905090565b60695460009061047d9063ffffffff6a0100000000000000000000820481169116611430565b6104b0610833565b6104ba6000610971565b565b6104c4610833565b6104ce82826109e8565b5050565b6104da610833565b61045081610a79565b6104eb610833565b61045081610b57565b6104fc610833565b61045081610fcb565b61050d610833565b73ffffffffffffffffffffffffffffffffffffffff81166105b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61045081610971565b600054610100900460ff16158080156105de5750600054600160ff909116105b806105f85750303b1580156105f8575060005460ff166001145b610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105ac565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106e257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6106ea610ff3565b6106f388610505565b6106fc85610fcb565b61070687876109e8565b61070f84610a79565b610718836108b4565b61072182610b57565b610729610482565b67ffffffffffffffff168467ffffffffffffffff1610156107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b801561080957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b6108dd7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161096591906111e3565b60405180910390a35050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610a6c91906111e3565b60405180910390a3505050565b610a81610482565b67ffffffffffffffff168167ffffffffffffffff161015610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610934565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610c07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016105ac565b6001816040015160ff1611610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016105ac565b6068546080820151825167ffffffffffffffff90921691610cbf919061145c565b63ffffffff161115610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b6000816020015160ff1611610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016105ac565b8051602082015163ffffffff82169160ff90911690610de490829061147b565b610dee91906114c5565b63ffffffff1614610e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016105ac565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6067819055604080516020808201849052825180830390910181529082019091526000610934565b600054610100900460ff1661108a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba600054610100900460ff16611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba33610971565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115157600080fd5b919050565b60006020828403121561116857600080fd5b6111718261112d565b9392505050565b6000815180845260005b8181101561119e57602081850181015186830182015201611182565b818111156111b0576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111716020830184611178565b6000806040838503121561120957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461115157600080fd5b60006020828403121561124257600080fd5b61117182611218565b803563ffffffff8116811461115157600080fd5b803560ff8116811461115157600080fd5b80356fffffffffffffffffffffffffffffffff8116811461115157600080fd5b600060c082840312156112a257600080fd5b60405160c0810181811067ffffffffffffffff821117156112ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806112fb8361124b565b81526113096020840161125f565b602082015261131a6040840161125f565b604082015261132b6060840161124b565b606082015261133c6080840161124b565b608082015261134d60a08401611270565b60a08201525092915050565b600060c0828403121561136b57600080fd5b6111718383611290565b60006020828403121561138757600080fd5b5035919050565b6000806000806000806000610180888a0312156113aa57600080fd5b6113b38861112d565b96506020880135955060408801359450606088013593506113d660808901611218565b92506113e460a0890161112d565b91506113f38960c08a01611290565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561145357611453611401565b01949350505050565b600063ffffffff80831681851680830382111561145357611453611401565b600063ffffffff808416806114b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156114e8576114e8611401565b0294935050505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_batcherHash": "Initial batcher hash.", + "_config": "Initial resource config.", + "_gasLimit": "Initial gas limit.", + "_overhead": "Initial overhead value.", + "_owner": "Initial owner of the contract.", + "_scalar": "Initial scalar value.", + "_unsafeBlockSigner": "Initial unsafe block signer address." + } + }, + "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))": { + "params": { + "_batcherHash": "Initial batcher hash.", + "_config": "Initial ResourceConfig.", + "_gasLimit": "Initial gas limit.", + "_overhead": "Initial overhead value.", + "_owner": "Initial owner of the contract.", + "_scalar": "Initial scalar value.", + "_unsafeBlockSigner": "Initial unsafe block signer address." + } + }, + "minimumGasLimit()": { + "returns": { + "_0": "uint64 Minimum gas limit." + } + }, + "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." + }, + "resourceConfig()": { + "returns": { + "_0": "ResourceConfig" + } + }, + "setBatcherHash(bytes32)": { + "params": { + "_batcherHash": "New batcher hash." + } + }, + "setGasConfig(uint256,uint256)": { + "params": { + "_overhead": "New overhead value.", + "_scalar": "New scalar value." + } + }, + "setGasLimit(uint64)": { + "params": { + "_gasLimit": "New gas limit." + } + }, + "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { + "params": { + "_config": "The new resource config values." + } + }, + "setUnsafeBlockSigner(address)": { + "params": { + "_unsafeBlockSigner": "New unsafe block signer address." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsafeBlockSigner()": { + "returns": { + "addr_": "Address of the unsafe block signer." + } + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "params": { + "data": "Encoded update data.", + "updateType": "Type of update.", + "version": "SystemConfig version." + } + } + }, + "title": "SystemConfig" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum SystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"resourceConfig\",\"outputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setBatcherHash\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasConfig\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasLimit\"},{\"inputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setResourceConfig\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUnsafeBlockSigner\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial resource config.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial ResourceConfig.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"minimumGasLimit()\":{\"returns\":{\"_0\":\"uint64 Minimum gas limit.\"}},\"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.\"},\"resourceConfig()\":{\"returns\":{\"_0\":\"ResourceConfig\"}},\"setBatcherHash(bytes32)\":{\"params\":{\"_batcherHash\":\"New batcher hash.\"}},\"setGasConfig(uint256,uint256)\":{\"params\":{\"_overhead\":\"New overhead value.\",\"_scalar\":\"New scalar value.\"}},\"setGasLimit(uint64)\":{\"params\":{\"_gasLimit\":\"New gas limit.\"}},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_config\":\"The new resource config values.\"}},\"setUnsafeBlockSigner(address)\":{\"params\":{\"_unsafeBlockSigner\":\"New unsafe block signer address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsafeBlockSigner()\":{\"returns\":{\"addr_\":\"Address of the unsafe block signer.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"UNSAFE_BLOCK_SIGNER_SLOT()\":{\"notice\":\"Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"batcherHash()\":{\"notice\":\"Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes.\"},\"constructor\":{\"notice\":\"Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`\"},\"gasLimit()\":{\"notice\":\"L2 block gas limit.\"},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"Initializer. The resource config must be set before the require check.\"},\"minimumGasLimit()\":{\"notice\":\"Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe.\"},\"overhead()\":{\"notice\":\"Fixed L2 gas overhead. Used as part of the L2 fee calculation.\"},\"resourceConfig()\":{\"notice\":\"A getter for the resource config. Ensures that the struct is returned instead of a tuple.\"},\"scalar()\":{\"notice\":\"Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\"},\"setBatcherHash(bytes32)\":{\"notice\":\"Updates the batcher hash. Can only be called by the owner.\"},\"setGasConfig(uint256,uint256)\":{\"notice\":\"Updates gas config. Can only be called by the owner.\"},\"setGasLimit(uint64)\":{\"notice\":\"Updates the L2 gas limit. Can only be called by the owner.\"},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed.\"},\"setUnsafeBlockSigner(address)\":{\"notice\":\"Updates the unsafe block signer address. Can only be called by the owner.\"},\"unsafeBlockSigner()\":{\"notice\":\"High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SystemConfig.sol\":\"SystemConfig\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0x2f8dc0", + "gasUsed": "0x14f3ca", + "contractAddress": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "logs": [ + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be" + ], + "data": "0x", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x0", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000078697c88847dfbbb40523e42c1f2e28a13a170be", + "0x000000000000000000000000000000000000000000000000000000000000dead" + ], + "data": "0x", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x1", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x2", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x3", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000001406f40", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x4", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x5", + "removed": false + }, + { + "address": "0x5DD520681C01ace09d46C9Cc7228864715971f68", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xe1379b86a57eff8c058053b17c63565efa68a14ca1781f70bd1e5e0d810076c8", + "blockNumber": "0xb", + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "transactionIndex": "0x1", + "logIndex": "0x6", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x04000000000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000020008000000000000040000000000000000000000000000000020000001000000040000000000000000000000000000020000010000000000000800000000000000000000000000000000400001000000000000000004040000000000200000000088000000000000000000000000000000000000000100000400000000000000800000000000000000400008000400000000000000000000040000000000000000000000000000000060000000000000000000000000000000000000000000008000000000008000000000", + "type": "0x2", + "effectiveGasPrice": "0xc8a19b94" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 44768, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 44771, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 46299, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 44640, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 44760, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 78518, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "overhead", + "offset": 0, + "slot": "101", + "type": "t_uint256" + }, + { + "astId": 78521, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "scalar", + "offset": 0, + "slot": "102", + "type": "t_uint256" + }, + { + "astId": 78524, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "batcherHash", + "offset": 0, + "slot": "103", + "type": "t_bytes32" + }, + { + "astId": 78527, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "gasLimit", + "offset": 0, + "slot": "104", + "type": "t_uint64" + }, + { + "astId": 78531, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "_resourceConfig", + "offset": 0, + "slot": "105", + "type": "t_struct(ResourceConfig)77955_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_struct(ResourceConfig)77955_storage": { + "encoding": "inplace", + "label": "struct ResourceMetering.ResourceConfig", + "numberOfBytes": "32", + "members": [ + { + "astId": 77944, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "maxResourceLimit", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 77946, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "elasticityMultiplier", + "offset": 4, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 77948, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "baseFeeMaxChangeDenominator", + "offset": 5, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 77950, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "minimumBaseFee", + "offset": 6, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 77952, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "systemTxMaxGas", + "offset": 10, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 77954, + "contract": "src/L1/SystemConfig.sol:SystemConfig", + "label": "maximumBaseFee", + "offset": 14, + "slot": "0", + "type": "t_uint128" + } + ] + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0x29e8647aaa9d9782f840348f9755104b926e820b6f73f023b5136f73ec9e7b56", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "UNSAFE_BLOCK_SIGNER_SLOT()": { + "notice": "Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value." + }, + "VERSION()": { + "notice": "Version identifier, used for upgrades." + }, + "batcherHash()": { + "notice": "Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes." + }, + "constructor": { + "notice": "Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`" + }, + "gasLimit()": { + "notice": "L2 block gas limit." + }, + "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))": { + "notice": "Initializer. The resource config must be set before the require check." + }, + "minimumGasLimit()": { + "notice": "Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe." + }, + "overhead()": { + "notice": "Fixed L2 gas overhead. Used as part of the L2 fee calculation." + }, + "resourceConfig()": { + "notice": "A getter for the resource config. Ensures that the struct is returned instead of a tuple." + }, + "scalar()": { + "notice": "Dynamic L2 gas overhead. Used as part of the L2 fee calculation." + }, + "setBatcherHash(bytes32)": { + "notice": "Updates the batcher hash. Can only be called by the owner." + }, + "setGasConfig(uint256,uint256)": { + "notice": "Updates gas config. Can only be called by the owner." + }, + "setGasLimit(uint64)": { + "notice": "Updates the L2 gas limit. Can only be called by the owner." + }, + "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { + "notice": "An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed." + }, + "setUnsafeBlockSigner(address)": { + "notice": "Updates the unsafe block signer address. Can only be called by the owner." + }, + "unsafeBlockSigner()": { + "notice": "High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "notice": "Emitted when configuration is updated." + } + }, + "notice": "The SystemConfig contract is used to manage configuration of an Optimism network. All configuration is stored on L1 and picked up by L2 as part of the derviation of the L2 chain." + } +} \ No newline at end of file diff --git a/e2e/deployments/devnetL1/SystemConfigProxy.json b/e2e/deployments/devnetL1/SystemConfigProxy.json new file mode 100644 index 000000000000..a62a9b3482ea --- /dev/null +++ b/e2e/deployments/devnetL1/SystemConfigProxy.json @@ -0,0 +1,256 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "fallback", + "stateMutability": "payable" + }, + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "admin", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "changeAdmin", + "inputs": [ + { + "name": "_admin", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "implementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeTo", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "upgradeToAndCall", + "inputs": [ + { + "name": "_implementation", + "type": "address", + "internalType": "address" + }, + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "payable" + }, + { + "type": "event", + "name": "AdminChanged", + "inputs": [ + { + "name": "previousAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAdmin", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Upgraded", + "inputs": [ + { + "name": "implementation", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + } + ], + "address": "0x654fe8bC4F8Bf51f0CeC4567399aD7067E145C3F", + "args": [ + "0x1D4ed8572c78bf7146358183694284453C5B0C58" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 12, + "receipt": { + "transactionHash": "0x53632ea215a2d1a2966d11d0a67296e1c154862007c543df8374b807024b40b5", + "transactionIndex": "0xf", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "from": "0x78697c88847DFbbB40523E42c1f2e28a13A170bE", + "to": null, + "cumulativeGasUsed": "0xa2ca3d", + "gasUsed": "0x80250", + "contractAddress": "0x654fe8bC4F8Bf51f0CeC4567399aD7067E145C3F", + "logs": [ + { + "address": "0x654fe8bC4F8Bf51f0CeC4567399aD7067E145C3F", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d4ed8572c78bf7146358183694284453c5b0c58", + "blockHash": "0x493c87ad544312b51af302c7046b7dafb40d801f1b13366d74631d861a816494", + "blockNumber": "0x9", + "transactionHash": "0x53632ea215a2d1a2966d11d0a67296e1c154862007c543df8374b807024b40b5", + "transactionIndex": "0xf", + "logIndex": "0x1c", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000800", + "type": "0x2", + "effectiveGasPrice": "0xc4cf7cd1" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x53632ea215a2d1a2966d11d0a67296e1c154862007c543df8374b807024b40b5", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 825f10f05298..da102f4227f3 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -1,3 +1,8 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + + version: '3' services: bitcoind: @@ -12,6 +17,10 @@ services: - '-txindex=1' ports: - 18443:18443 + - 18444:18444 + volumes: + - type: tmpfs + target: /bitcoin/.bitcoin initialblocks: image: 'kylemanna/bitcoind' @@ -24,7 +33,7 @@ services: - '-rpcconnect=bitcoind' - 'generatetoaddress' - '300' # need to generate a lot for greater chance to not spend coinbase - - 'mw47rj9rG25J67G6W8bbjRayRQjWN5ZSEG' + - $BTC_ADDRESS depends_on: - bitcoind @@ -39,22 +48,23 @@ services: - '-rpcconnect=bitcoind' - 'generatetoaddress' - '1' - - 'mw47rj9rG25J67G6W8bbjRayRQjWN5ZSEG' + - $BTC_ADDRESS deploy: restart_policy: condition: any - delay: 5s depends_on: - bitcoind - electrumx: image: 'lukechilds/electrumx' environment: DAEMON_URL: 'http://user:password@bitcoind:18443' - COIN: 'BitcoinSegwit' + COIN: 'Bitcoin' + COST_HARD_LIMIT: '0' + COST_SOFT_LIMIT: '0' + MAX_SEND: '8388608' NET: 'regtest' ports: - - 50001:50001 + - 50001:8000 depends_on: - bitcoind @@ -67,6 +77,9 @@ services: POSTGRES_HOST_AUTH_METHOD: "trust" ports: - 5432:5432 + volumes: + - type: tmpfs + target: /var bfgd: build: @@ -74,9 +87,9 @@ services: context: ./.. environment: BFG_POSTGRES_URI: postgres://postgres@postgres:5432/bfg?sslmode=disable - BFG_BTC_START_HEIGHT: "100" + BFG_BTC_START_HEIGHT: "1" BFG_EXBTC_ADDRESS: electrumx:50001 - BFG_LOG_LEVEL: TRACE + BFG_LOG_LEVEL: INFO BFG_PUBLIC_ADDRESS: ":8383" BFG_PRIVATE_ADDRESS: ":8080" ports: @@ -84,6 +97,9 @@ services: - 8383:8383 depends_on: - postgres + deploy: + restart_policy: + condition: any bssd: build: @@ -91,7 +107,7 @@ services: context: ./.. environment: BSS_BFG_URL: 'ws://bfgd:8080/v1/ws/private' - BSS_LOG_LEVEL: TRACE + BSS_LOG_LEVEL: INFO BSS_ADDRESS: ':8081' ports: - 8081:8081 @@ -103,18 +119,156 @@ services: dockerfile: ./docker/popmd/Dockerfile context: ./.. environment: - POPM_BTC_PRIVKEY: '72a2c41c84147325ce3c0f37697ef1e670c7169063dda89be9995c3c5219740f' + POPM_BTC_PRIVKEY: ${POPM_BTC_PRIVATE_KEY} POPM_BFG_URL: http://bfgd:8383/v1/ws/public - POPM_LOG_LEVEL: TRACE + POPM_LOG_LEVEL: INFO + POPM_REMINE_THRESHOLD: '1' depends_on: - bfgd - - mocktimism: + op-geth-l1: + image: ethereum/client-go:v1.13.14 + command: + - --dev + - --dev.period + - '3' + - --keystore + - /tmp/keystore + - --password + - /tmp/passwords.txt + - --http + - --http.port=8545 + - --http.addr + - '0.0.0.0' + - --http.vhosts + - '*' + - --syncmode=full + - --gcmode=archive + - --nodiscover + - --maxpeers=0 + - --authrpc.vhosts="*" + - --rpc.allow-unprotected-txs + - --datadir + - /tmp/geth + - --gpo.percentile=0 + ports: + - 8545:8545 + working_dir: /tmp/geth + volumes: + - ./e2e/keystore:/tmp/keystore:ro + - ./e2e/passwords.txt:/tmp/passwords.txt:ro + - ./e2e/jwt.txt:/tmp/jwt.txt:ro + - geth:/tmp/geth + - type: tmpfs + target: /tmp + environment: + CHAIN_ID: '900' + op-geth-l2: build: - dockerfile: ./e2e/mocktimism/Dockerfile - context: ./.. + dockerfile: optimism-stack.Dockerfile + context: . + command: + - sh + - /tmp/entrypointl2.sh environment: - MOCKTIMISM_BSS_URL: http://bssd:8081/v1/ws + ADMIN_PRIVATE_KEY: ${ADMIN_PRIVATE_KEY} + OP_GETH_L1_RPC: 'http://op-geth-l1:8545' + ports: + - 8551:8551 + - 8546:8546 + volumes: + - ./e2e/keystore:/tmp/keystore:ro + - ./e2e/passwords.txt:/tmp/passwords.txt:ro + - ./jwt.txt:/tmp/jwt.txt:ro + - ./entrypointl2.sh:/tmp/entrypointl2.sh + - ./genesisl2.sh:/tmp/genesisl2.sh + - ./output:/tmp/output + - l2configs:/l2configs + - ./deploy-config.json:/git/optimism/packages/contracts-bedrock/deploy-config/devnetL1.json + - ./deployments:/git/optimism/packages/contracts-bedrock/deployments + - ./prestate-proof.json:/git/optimism/op-program/bin/prestate-proof.json + - type: tmpfs + target: /tmp + working_dir: /tmp + depends_on: + - op-geth-l1 + op-node: + build: + dockerfile: optimism-stack.Dockerfile + context: . + command: + - op-node/bin/op-node + - --l2=ws://op-geth-l2:8551 + - --l2.jwt-secret=/tmp/jwt.txt + - --sequencer.enabled + - --sequencer.l1-confs=0 + - --verifier.l1-confs=0 + - --rollup.config=/l2configs/rollup.json + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --p2p.disable + - --rpc.enable-admin + - --l1=http://op-geth-l1:8545 + - --l1.rpckind=standard + - --l1.trustrpc + - --log.level=trace + - --l1.trustrpc=true + - --l1.http-poll-interval=1s + volumes: + - l2configs:/l2configs + - ./jwt.txt:/tmp/jwt.txt depends_on: - - bssd - + - op-geth-l1 + - op-geth-l2 + environment: + OP_NODE_BSS_WS: http://bssd:8081/v1/ws + deploy: + restart_policy: + condition: any + op-batcher: + build: + dockerfile: optimism-stack.Dockerfile + context: . + command: + - op-batcher/bin/op-batcher + - --l2-eth-rpc=http://op-geth-l2:8546 + - --rollup-rpc=http://op-node:8547 + - --poll-interval=1s + - --sub-safety-margin=1 + - --num-confirmations=1 + - --safe-abort-nonce-too-low-count=3 + - --resubmission-timeout=30s + - --rpc.addr=0.0.0.0 + - --rpc.port=8548 + - --rpc.enable-admin + - --max-channel-duration=1 + - --max-pending-tx=1 + - --l1-eth-rpc=http://op-geth-l1:8545 + - --private-key=${ADMIN_PRIVATE_KEY} + - op-geth-l1 + - op-geth-l2 + - op-node + deploy: + restart_policy: + condition: any + op-proposer: + build: + dockerfile: optimism-stack.Dockerfile + context: . + command: + - op-proposer/bin/op-proposer + - --poll-interval=1s + - --rpc.port=8560 + - --rollup-rpc=http://op-node:8547 + - --l2oo-address=${L2OO_ADDRESS} + - --private-key=${ADMIN_PRIVATE_KEY} + - --l1-eth-rpc=http://op-geth-l1:8545 + depends_on: + - op-geth-l1 + - op-geth-l2 + - op-node + deploy: + restart_policy: + condition: any +volumes: + geth: + l2configs: diff --git a/e2e/e2e/keystore/UTC--2024-03-05T21-11-00.982268400Z--78697c88847dfbbb40523e42c1f2e28a13a170be b/e2e/e2e/keystore/UTC--2024-03-05T21-11-00.982268400Z--78697c88847dfbbb40523e42c1f2e28a13a170be new file mode 100644 index 000000000000..e7efc2392a6e --- /dev/null +++ b/e2e/e2e/keystore/UTC--2024-03-05T21-11-00.982268400Z--78697c88847dfbbb40523e42c1f2e28a13a170be @@ -0,0 +1 @@ +{"address":"78697c88847dfbbb40523e42c1f2e28a13a170be","crypto":{"cipher":"aes-128-ctr","ciphertext":"f579ee05fd4ca7b76b9b1ca0474ebb229567a1aaa020a6a9a0933ddd66b43160","cipherparams":{"iv":"48523c4a70f6b4391b5eebaff4a90522"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e64a1590eac2be0f9187a86ff3b283d0e83d473616682c8c3c93b12e019c8fdb"},"mac":"d19072f80ebc2f99e017040f861588db0d574d6402f027ba1747a02a26f00b3d"},"id":"8b742e58-dd11-42cb-b54d-e266223635ec","version":3} \ No newline at end of file diff --git a/e2e/e2e/keystore/UTC--2024-03-05T21-11-09.690910600Z--06f0f8ee8119b2a0b7a95ba267231be783d8d2ab b/e2e/e2e/keystore/UTC--2024-03-05T21-11-09.690910600Z--06f0f8ee8119b2a0b7a95ba267231be783d8d2ab new file mode 100644 index 000000000000..d12029364020 --- /dev/null +++ b/e2e/e2e/keystore/UTC--2024-03-05T21-11-09.690910600Z--06f0f8ee8119b2a0b7a95ba267231be783d8d2ab @@ -0,0 +1 @@ +{"address":"06f0f8ee8119b2a0b7a95ba267231be783d8d2ab","crypto":{"cipher":"aes-128-ctr","ciphertext":"ffcca0aa0808a64647dcc6bd33db10f66240991ff5d7591708fe6d880ac0515d","cipherparams":{"iv":"be94e052af21eb0e1fe1ed924cbe8570"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"f362feac0d65185209f08b5b737fd4674df017bb76ef09863bd0ea7c5aa5851c"},"mac":"de835058708c2fc0c7342d840781b088a74aa8777ea38bbcb0bc7ec86f1e2253"},"id":"5133162a-5af5-40e2-bb0e-36f3bd8160c9","version":3} \ No newline at end of file diff --git a/e2e/e2e/keystore/UTC--2024-03-05T21-11-16.934955400Z--7e7b60b907135c1a3d6844cfd3760b3143f5497a b/e2e/e2e/keystore/UTC--2024-03-05T21-11-16.934955400Z--7e7b60b907135c1a3d6844cfd3760b3143f5497a new file mode 100644 index 000000000000..6225f63a5c2d --- /dev/null +++ b/e2e/e2e/keystore/UTC--2024-03-05T21-11-16.934955400Z--7e7b60b907135c1a3d6844cfd3760b3143f5497a @@ -0,0 +1 @@ +{"address":"7e7b60b907135c1a3d6844cfd3760b3143f5497a","crypto":{"cipher":"aes-128-ctr","ciphertext":"83a748a8f9243b3b9d72de3221e5f3027afdb87aca221710c0b4b9ab2de407b0","cipherparams":{"iv":"ba5143b326ee26c0453d308b9d79f6c3"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b3b649046f82e26ae76e828f5247420ef287b74dedd92aa2022de41a830e0284"},"mac":"3b09209a10eb96e0a9ebabfcb12d511465321b07f402a1f0576fc7d1016ec02a"},"id":"4214b869-cce9-4255-9659-f0ccd10036b6","version":3} \ No newline at end of file diff --git a/e2e/e2e/passwords.txt b/e2e/e2e/passwords.txt new file mode 100644 index 000000000000..0f3d06cacb63 --- /dev/null +++ b/e2e/e2e/passwords.txt @@ -0,0 +1 @@ +blahblahblah \ No newline at end of file diff --git a/e2e/e2e_ext_test.go b/e2e/e2e_ext_test.go index ce694d0bf362..38052e1bc82c 100644 --- a/e2e/e2e_ext_test.go +++ b/e2e/e2e_ext_test.go @@ -11,6 +11,7 @@ import ( "encoding/binary" "encoding/hex" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -260,7 +261,7 @@ func createTestDB(ctx context.Context, t *testing.T) (bfgd.Database, string, *sq func nextPort() int { port, err := freeport.GetFreePort() - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { panic(err) } @@ -298,7 +299,7 @@ func createBfgServerWithAuth(ctx context.Context, t *testing.T, pgUri string, el go func() { err := bfgServer.Run(ctx) - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { panic(err) } }() @@ -334,7 +335,7 @@ func createBssServer(ctx context.Context, t *testing.T, bfgWsurl string) (*bss.S go func() { err := bssServer.Run(ctx) - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { panic(err) } }() @@ -389,183 +390,197 @@ func createMockElectrumxServer(ctx context.Context, t *testing.T, l2Keystone *he panic(err) } - buf := make([]byte, 1000) - n, err := conn.Read(buf) - if err != nil { - t.Logf( - "error occurred reading from conn, will listen again: %s", - err.Error(), - ) - conn.Close() - continue - } + go handleMockElectrumxConnection(ctx, t, conn, btx) + } + }() - req := electrumx.JSONRPCRequest{} - err = json.Unmarshal(buf[:n], &req) - if err != nil { - panic(err) - } + return addr, cleanup +} - res := electrumx.JSONRPCResponse{} - if req.Method == "blockchain.transaction.broadcast" { - res.ID = req.ID - res.Error = nil - res.Result = json.RawMessage([]byte(fmt.Sprintf("\"%s\"", mockTxHash))) - } +func handleMockElectrumxConnection(ctx context.Context, t *testing.T, conn net.Conn, btx []byte) { + t.Helper() + defer conn.Close() - if req.Method == "blockchain.headers.subscribe" { - res.ID = req.ID - res.Error = nil - headerNotification := electrumx.HeaderNotification{ - Height: mockTxheight, - BinaryHeader: "aaaa", - } + t.Logf("Handling connection: %s", conn.RemoteAddr()) - b, err := json.Marshal(&headerNotification) - if err != nil { - panic(err) - } + for { + select { + case <-ctx.Done(): + return + default: + } + + buf := make([]byte, 1000) + n, err := conn.Read(buf) + if err != nil { + t.Logf( + "error occurred reading from conn, will listen again: %s", + err.Error(), + ) + return + } + + req := electrumx.JSONRPCRequest{} + err = json.Unmarshal(buf[:n], &req) + if err != nil { + panic(err) + } - res.Result = b + res := electrumx.JSONRPCResponse{} + if req.Method == "blockchain.transaction.broadcast" { + res.ID = req.ID + res.Error = nil + res.Result = json.RawMessage([]byte(fmt.Sprintf("\"%s\"", mockTxHash))) + } + + if req.Method == "blockchain.headers.subscribe" { + res.ID = req.ID + res.Error = nil + headerNotification := electrumx.HeaderNotification{ + Height: mockTxheight, + BinaryHeader: "aaaa", } - if req.Method == "blockchain.block.header" { - res.ID = req.ID - res.Error = nil - res.Result = json.RawMessage([]byte(mockEncodedBlockHeader)) + b, err := json.Marshal(&headerNotification) + if err != nil { + panic(err) } - if req.Method == "blockchain.transaction.id_from_pos" { - res.ID = req.ID - res.Error = nil - params := struct { - Height uint64 `json:"height"` - TXPos uint64 `json:"tx_pos"` - Merkle bool `json:"merkle"` - }{} + res.Result = b + } - err := json.Unmarshal(req.Params, ¶ms) - if err != nil { - panic(err) - } + if req.Method == "blockchain.block.header" { + res.ID = req.ID + res.Error = nil + res.Result = json.RawMessage([]byte(mockEncodedBlockHeader)) + } - result := struct { - TXHash string `json:"tx_hash"` - Merkle []string `json:"merkle"` - }{} + if req.Method == "blockchain.transaction.id_from_pos" { + res.ID = req.ID + res.Error = nil + params := struct { + Height uint64 `json:"height"` + TXPos uint64 `json:"tx_pos"` + Merkle bool `json:"merkle"` + }{} - t.Logf("checking height %d, pos %d", params.Height, params.TXPos) + err := json.Unmarshal(req.Params, ¶ms) + if err != nil { + panic(err) + } - if params.TXPos == mockTxPos && params.Height == mockTxheight { - result.TXHash = reverseAndEncodeEncodedHash(mockTxHash) - result.Merkle = mockMerkleHashes - } + result := struct { + TXHash string `json:"tx_hash"` + Merkle []string `json:"merkle"` + }{} - // pretend that there are no transactions past mockTxHeight - // and mockTxPos - if params.Height >= mockTxheight && params.TXPos > mockTxPos { - res.Error = electrumx.NewJSONRPCError(1, "no tx at pos") - } + t.Logf("checking height %d, pos %d", params.Height, params.TXPos) - b, err := json.Marshal(&result) - if err != nil { - panic(err) - } - - res.Result = b + if params.TXPos == mockTxPos && params.Height == mockTxheight { + result.TXHash = reverseAndEncodeEncodedHash(mockTxHash) + result.Merkle = mockMerkleHashes } - if req.Method == "blockchain.transaction.get" { - res.ID = req.ID - res.Error = nil + // pretend that there are no transactions past mockTxHeight + // and mockTxPos + if params.Height >= mockTxheight && params.TXPos > mockTxPos { + res.Error = electrumx.NewJSONRPCError(1, "no tx at pos") + } - params := struct { - TXHash string `json:"tx_hash"` - Verbose bool `json:"verbose"` - }{} + b, err := json.Marshal(&result) + if err != nil { + panic(err) + } - err := json.Unmarshal(req.Params, ¶ms) - if err != nil { - panic(err) - } + res.Result = b + } - if params.TXHash == reverseAndEncodeEncodedHash(mockTxHash) { - j, err := json.Marshal(hex.EncodeToString(btx)) - if err != nil { - panic(err) - } - res.Result = j - } - } + if req.Method == "blockchain.transaction.get" { + res.ID = req.ID + res.Error = nil - if req.Method == "blockchain.scripthash.get_balance" { - res.ID = req.ID - res.Error = nil - j, err := json.Marshal(electrumx.Balance{ - Confirmed: 1, - Unconfirmed: 2, - }) - if err != nil { - panic(err) - } + params := struct { + TXHash string `json:"tx_hash"` + Verbose bool `json:"verbose"` + }{} - res.Result = j + err := json.Unmarshal(req.Params, ¶ms) + if err != nil { + panic(err) } - if req.Method == "blockchain.headers.subscribe" { - res.ID = req.ID - res.Error = nil - j, err := json.Marshal(electrumx.HeaderNotification{ - Height: 10, - }) + if params.TXHash == reverseAndEncodeEncodedHash(mockTxHash) { + j, err := json.Marshal(hex.EncodeToString(btx)) if err != nil { panic(err) } res.Result = j } + } - if req.Method == "blockchain.scripthash.listunspent" { - res.ID = req.ID - res.Error = nil - hash := []byte{ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, - } - _j := []struct { - Hash string `json:"tx_hash"` - Height uint64 `json:"height"` - Index uint64 `json:"tx_pos"` - Value uint64 `json:"value"` - }{{ - Height: 99, - Hash: hex.EncodeToString(hash), - Index: 9999, - Value: 999999, - }} - j, err := json.Marshal(_j) - if err != nil { - panic(err) - } - - res.Result = j + if req.Method == "blockchain.scripthash.get_balance" { + res.ID = req.ID + res.Error = nil + j, err := json.Marshal(electrumx.Balance{ + Confirmed: 1, + Unconfirmed: 2, + }) + if err != nil { + panic(err) } - b, err := json.Marshal(res) + res.Result = j + } + + if req.Method == "blockchain.headers.subscribe" { + res.ID = req.ID + res.Error = nil + j, err := json.Marshal(electrumx.HeaderNotification{ + Height: 10, + }) if err != nil { panic(err) } + res.Result = j + } - b = append(b, '\n') - _, err = io.Copy(conn, bytes.NewReader(b)) + if req.Method == "blockchain.scripthash.listunspent" { + res.ID = req.ID + res.Error = nil + hash := []byte{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, + } + _j := []struct { + Hash string `json:"tx_hash"` + Height uint64 `json:"height"` + Index uint64 `json:"tx_pos"` + Value uint64 `json:"value"` + }{{ + Height: 99, + Hash: hex.EncodeToString(hash), + Index: 9999, + Value: 999999, + }} + j, err := json.Marshal(_j) if err != nil { panic(err) } - conn.Close() + res.Result = j } - }() - return addr, cleanup + b, err := json.Marshal(res) + if err != nil { + panic(err) + } + + b = append(b, '\n') + _, err = io.Copy(conn, bytes.NewReader(b)) + if err != nil { + panic(err) + } + } } func defaultTestContext() (context.Context, context.CancelFunc) { @@ -980,7 +995,7 @@ func TestBFGPublicErrorCases(t *testing.T) { }, { name: "bitcoin broadcast deserialize error", - expectedError: "failed to deserialized tx: unexpected EOF", + expectedError: "failed to deserialize tx: unexpected EOF", requests: []bfgapi.BitcoinBroadcastRequest{ { Transaction: []byte("invalid..."), @@ -1000,7 +1015,7 @@ func TestBFGPublicErrorCases(t *testing.T) { }, { name: "bitcoin broadcast database error", - expectedError: "pop_basis already exists", + expectedError: "pop basis already exists", requests: []bfgapi.BitcoinBroadcastRequest{ { Transaction: btx, @@ -1158,7 +1173,7 @@ func TestBFGPrivateErrorCases(t *testing.T) { }, { name: "public key is invalid", - expectedError: "encoding/hex: invalid byte: U+006C 'l'", + expectedError: "public key decode: encoding/hex: invalid byte: U+006C 'l'", requests: []bfgapi.AccessPublicKeyCreateRequest{ { PublicKey: "blahblahblah", @@ -3315,7 +3330,7 @@ func TestBFGAuthPingThenRemoval(t *testing.T) { var v interface{} err = wsjson.Read(ctx, c, &v) - if err != nil && !strings.Contains(err.Error(), "status = StatusCode(4100)") { + if err != nil && !strings.Contains(err.Error(), "status = StatusProtocolError and reason = \"killed\"") { t.Fatal(err) } diff --git a/e2e/entrypointl2.sh b/e2e/entrypointl2.sh new file mode 100644 index 000000000000..7e8f51589f93 --- /dev/null +++ b/e2e/entrypointl2.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + + +set -xe + +sh /tmp/genesisl2.sh + +/git/op-geth/build/bin/geth init --datadir /tmp/datadir /l2configs/genesis.json + +/git/op-geth/build/bin/geth \ + --keystore \ + /tmp/keystore \ + --password \ + /tmp/passwords.txt \ + --http \ + --http.port=8546 \ + --http.addr \ + '0.0.0.0' \ + --http.vhosts \ + '*' \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port=28546 \ + --ws.origins="*" \ + --ws.api=debug,eth,txpool,net,engine \ + --syncmode=full \ + --gcmode=archive \ + --nodiscover \ + --maxpeers=0 \ + --networkid=901 \ + --authrpc.vhosts="*" \ + --rpc.allow-unprotected-txs \ + --datadir \ + /tmp/datadir \ + --authrpc.vhosts="*" \ + --authrpc.addr=0.0.0.0 \ + --authrpc.port=8551 \ + --authrpc.jwtsecret=/tmp/jwt.txt \ + --verbosity=5 \ + --gpo.maxprice=1 \ No newline at end of file diff --git a/e2e/genesisl2.sh b/e2e/genesisl2.sh new file mode 100644 index 000000000000..2a2ab4e87172 --- /dev/null +++ b/e2e/genesisl2.sh @@ -0,0 +1,75 @@ +#! /bin/sh +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + +set -ex + +JSON_RPC=$OP_GETH_L1_RPC + +# start geth in a local container +# wait for geth to become responsive +until curl --silent --fail $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"net_version\", \"params\": []}"; do sleep 3; done + +sleep 3 + +# extract the variables we need from json output +MY_ADDRESS="0x78697c88847dfbbb40523e42c1f2e28a13a170be" +ONE_TIME_SIGNER_ADDRESS="0x$(cat output/deployment.json | jq --raw-output '.signerAddress')" +GAS_COST="0x$(printf '%x' $(($(cat output/deployment.json | jq --raw-output '.gasPrice') * $(cat output/deployment.json | jq --raw-output '.gasLimit'))))" +TRANSACTION="0x$(cat output/deployment.json | jq --raw-output '.transaction')" +DEPLOYER_ADDRESS="0x$(cat output/deployment.json | jq --raw-output '.address')" + + +sleep 3 + +# send gas money to signer +curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendTransaction\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$ONE_TIME_SIGNER_ADDRESS\",\"value\":\"$GAS_COST\"}]}" + +sleep 3 + +# deploy the deployer contract +curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendRawTransaction\", \"params\": [\"$TRANSACTION\"]}" + +sleep 3 + +# deploy our contract +# contract: pragma solidity 0.5.8; contract Apple {function banana() external pure returns (uint8) {return 42;}} +BYTECODE="6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c3cafc6f14602d575b600080fd5b6033604f565b604051808260ff1660ff16815260200191505060405180910390f35b6000602a90509056fea165627a7a72305820ab7651cb86b8c1487590004c2444f26ae30077a6b96c6bc62dda37f1328539250029" +MY_CONTRACT_ADDRESS=$(curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --silent --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_call\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$DEPLOYER_ADDRESS\", \"data\":\"0x0000000000000000000000000000000000000000000000000000000000000000$BYTECODE\"}, \"latest\"]}" | jq --raw-output '.result') + +sleep 3 + +curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_sendTransaction\", \"params\": [{\"from\":\"$MY_ADDRESS\",\"to\":\"$DEPLOYER_ADDRESS\", \"gas\":\"0xf4240\", \"data\":\"0x0000000000000000000000000000000000000000000000000000000000000000$BYTECODE\"}]}" + +sleep 3 + +# call our contract (NOTE: MY_CONTRACT_ADDRESS is the same no matter what chain we deploy to!) +MY_CONTRACT_METHOD_SIGNATURE="c3cafc6f" +curl $JSON_RPC -X 'POST' -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\": \"eth_call\", \"params\": [{\"to\":\"$MY_CONTRACT_ADDRESS\", \"data\":\"0x$MY_CONTRACT_METHOD_SIGNATURE\"}, \"latest\"]}" +# expected result is 0x000000000000000000000000000000000000000000000000000000000000002a (hex encoded 42) + +cd /git/optimism/packages/contracts-bedrock + +forge script ./scripts/Deploy.s.sol:Deploy --private-key=$ADMIN_PRIVATE_KEY --broadcast --rpc-url $JSON_RPC +forge script ./scripts/Deploy.s.sol:Deploy --sig 'sync()' --private-key=$ADMIN_PRIVATE_KEY --broadcast --rpc-url $JSON_RPC + +curl -H 'Content-Type: application/json' -X POST --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x2", true],"id":1}' $JSON_RPC > /tmp/blockl1.json + +echo $(jq '.result' /tmp/blockl1.json) > /tmp/blockl1.json + +cat /tmp/blockl1.json + +/git/optimism/op-node/bin/op-node \ + genesis \ + l2 \ + --deploy-config \ + /git/optimism/packages/contracts-bedrock/deploy-config/devnetL1.json \ + --deployment-dir \ + /git/optimism/packages/contracts-bedrock/deployments/devnetL1 \ + --outfile.l2 \ + /l2configs/genesis.json \ + --outfile.rollup \ + /l2configs/rollup.json \ + --l1-starting-block \ + /tmp/blockl1.json diff --git a/e2e/jwt.txt b/e2e/jwt.txt new file mode 100644 index 000000000000..a60405a6cccb --- /dev/null +++ b/e2e/jwt.txt @@ -0,0 +1 @@ +caa4d3f71fa10a2cd87923055f61f36a94e06f094e38ee080cc1f5babd0a620a \ No newline at end of file diff --git a/e2e/mocktimism/Dockerfile b/e2e/mocktimism/Dockerfile index df3e3a1f0b07..99959cc868ca 100644 --- a/e2e/mocktimism/Dockerfile +++ b/e2e/mocktimism/Dockerfile @@ -1,3 +1,7 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + FROM golang:1.22.0@sha256:03082deb6ae090a0caa4e4a8f666bc59715bc6fa67f5fd109f823a0c4e1efc2a WORKDIR /mocktimism diff --git a/e2e/mocktimism/mocktimism.go b/e2e/mocktimism/mocktimism.go index d32b6fed3e37..0ede521d5bdb 100644 --- a/e2e/mocktimism/mocktimism.go +++ b/e2e/mocktimism/mocktimism.go @@ -1,17 +1,24 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + package main import ( "context" + "fmt" "os" + "strconv" "sync" "time" "github.com/davecgh/go-spew/spew" + "github.com/juju/loggo" + "nhooyr.io/websocket" + "github.com/hemilabs/heminetwork/api/bssapi" "github.com/hemilabs/heminetwork/api/protocol" "github.com/hemilabs/heminetwork/hemi" - "github.com/juju/loggo" - "nhooyr.io/websocket" ) const logLevel = "INFO" @@ -89,7 +96,7 @@ func main() { l2Keystone.L1BlockNumber++ l2Keystone.L2BlockNumber++ - time.Sleep(1 * time.Second) + time.Sleep(time.Duration(l2BlockCreationSeconds()) * time.Second) err = bssapi.Write(ctx, bws.conn, "someotherid", bssapi.PopPayoutsRequest{ L2BlockForPayout: firstL2Keystone[:], @@ -122,3 +129,17 @@ func fillOutBytes(prefix string, size int) []byte { return result } + +func l2BlockCreationSeconds() int { + v := os.Getenv("MOCKTIMISM_L2K_RATE_SECONDS") + if v == "" { + return 1 + } + + i, err := strconv.Atoi(v) + if err != nil { + panic(fmt.Sprintf("invalid value for seconds: %s", v)) + } + + return i +} diff --git a/e2e/network_test.go b/e2e/network_test.go index a9476d000a5c..6e2fd2f4a268 100644 --- a/e2e/network_test.go +++ b/e2e/network_test.go @@ -1,3 +1,7 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + package e2e import ( @@ -16,14 +20,15 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + "nhooyr.io/websocket" + "github.com/hemilabs/heminetwork/api/bssapi" "github.com/hemilabs/heminetwork/api/protocol" "github.com/hemilabs/heminetwork/bitcoin" "github.com/hemilabs/heminetwork/ethereum" "github.com/hemilabs/heminetwork/hemi" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/wait" - "nhooyr.io/websocket" ) const ( @@ -88,7 +93,7 @@ func TestFullNetwork(t *testing.T) { "-rpcuser=user", "-rpcpassword=password", "generatetoaddress", - "300", // need to generate a lot for greater chance to not spend coinbase + "200", // need to generate a lot for greater chance to not spend coinbase btcAddress.EncodeAddress(), }) if err != nil { @@ -212,22 +217,27 @@ func TestFullNetwork(t *testing.T) { } }() - go func() { - // create a new block every second, then view pop payouts and finalities - - firstL2Keystone := hemi.L2KeystoneAbbreviate(l2Keystone).Serialize() + l2KeystoneRequest := bssapi.L2KeystoneRequest{ + L2Keystone: l2Keystone, + } - for { - l2KeystoneRequest := bssapi.L2KeystoneRequest{ - L2Keystone: l2Keystone, - } + err = bssapi.Write(ctx, bws.conn, "someid", l2KeystoneRequest) + if err != nil { + t.Logf("error: %s", err) + return + } - err = bssapi.Write(ctx, bws.conn, "someid", l2KeystoneRequest) - if err != nil { - t.Logf("error: %s", err) - return - } + // give time for the L2 Keystone to propogate to bitcoin tx mempool + select { + case <-time.After(10 * time.Second): + case <-ctx.Done(): + t.Logf(ctx.Err().Error()) + return + } + go func() { + for { + // generate a new btc block, this should include the l2 keystone err = runBitcoinCommand(ctx, t, bitcoindContainer, @@ -246,21 +256,18 @@ func TestFullNetwork(t *testing.T) { return } - l2Keystone.L1BlockNumber++ - l2Keystone.L2BlockNumber++ - - time.Sleep(1 * time.Second) - - err = bssapi.Write(ctx, bws.conn, "someotherid", bssapi.PopPayoutsRequest{ - L2BlockForPayout: firstL2Keystone[:], - }) - if err != nil { - t.Logf("error: %s", err) + // give time for bfg to see the new block + select { + case <-time.After(10 * time.Second): + case <-ctx.Done(): + t.Log(ctx.Err()) return } - err = bssapi.Write(ctx, bws.conn, "someotheridz", bssapi.BTCFinalityByRecentKeystonesRequest{ - NumRecentKeystones: 100, + // ensure the l2 keystone is in the chain + ks := hemi.L2KeystoneAbbreviate(l2Keystone).Serialize() + err = bssapi.Write(ctx, bws.conn, "someotherid", bssapi.PopPayoutsRequest{ + L2BlockForPayout: ks[:], }) if err != nil { t.Logf("error: %s", err) @@ -306,9 +313,12 @@ func createElectrumx(ctx context.Context, t *testing.T, bitcoindEndpoint string) req := testcontainers.ContainerRequest{ Image: "lukechilds/electrumx", Env: map[string]string{ - "DAEMON_URL": bitcoindEndpoint, - "COIN": "BitcoinSegwit", - "NET": "regtest", + "DAEMON_URL": bitcoindEndpoint, + "COIN": "Bitcoin", + "COST_HARD_LIMIT": "0", + "COST_SOFT_LIMIT": "0", + "MAX_SEND": "8388608", + "NET": "regtest", }, ExposedPorts: []string{"50001/tcp"}, WaitingFor: wait.ForLog("INFO:Daemon:daemon #1").WithPollInterval(1 * time.Second), @@ -379,7 +389,7 @@ func createBfg(ctx context.Context, t *testing.T, pgUri string, electrumxAddr st req := testcontainers.ContainerRequest{ Env: map[string]string{ "BFG_POSTGRES_URI": pgUri, - "BFG_BTC_START_HEIGHT": "100", + "BFG_BTC_START_HEIGHT": "1", "BFG_EXBTC_ADDRESS": electrumxAddr, "BFG_LOG_LEVEL": "TRACE", "BFG_PUBLIC_ADDRESS": ":8383", diff --git a/e2e/optimism-stack.Dockerfile b/e2e/optimism-stack.Dockerfile new file mode 100644 index 000000000000..11e28ed8cff2 --- /dev/null +++ b/e2e/optimism-stack.Dockerfile @@ -0,0 +1,51 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + +FROM golang:1.22 + +RUN apt-get update + +RUN apt-get install -y nodejs npm jq + +RUN npm install -g pnpm + +WORKDIR /git + +RUN curl -L https://foundry.paradigm.xyz | bash + +RUN . /root/.bashrc + +ENV PATH="${PATH}:/root/.foundry/bin" + +RUN foundryup + +ARG OP_GETH_CACHE_BREAK=1 + +RUN git clone https://github.com/hemilabs/op-geth +WORKDIR /git/op-geth +RUN git checkout hemi + +RUN make +RUN go install ./... +RUN abigen --version + +ARG OPTIMISM_CACHE_BREAK=1 + +WORKDIR /git +RUN git clone https://github.com/hemilabs/optimism +WORKDIR /git/optimism +RUN git checkout hemi +RUN git submodule update --init --recursive +RUN pnpm install +WORKDIR /git/optimism/packages/contracts-bedrock +RUN sed -e '/build_info/d' -i ./foundry.toml +WORKDIR /git/optimism +RUN make op-bindings op-node op-batcher op-proposer +RUN pnpm build + +WORKDIR /git/optimism/packages/contracts-bedrock +RUN forge install +RUN forge build + +WORKDIR /git/optimism \ No newline at end of file diff --git a/e2e/output/bytecode.txt b/e2e/output/bytecode.txt new file mode 100644 index 000000000000..3ce7049d9527 --- /dev/null +++ b/e2e/output/bytecode.txt @@ -0,0 +1 @@ +604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3 \ No newline at end of file diff --git a/e2e/output/deployment.json b/e2e/output/deployment.json new file mode 100644 index 000000000000..e001fbf5ceed --- /dev/null +++ b/e2e/output/deployment.json @@ -0,0 +1,7 @@ +{ + "gasPrice": 100000000000, + "gasLimit": 100000, + "signerAddress": "3fab184622dc19b6109349b94811493bf2a45362", + "transaction": "f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222", + "address": "4e59b44847b379578588920ca78fbf26c0b4956c" +} diff --git a/e2e/postgres.Dockerfile b/e2e/postgres.Dockerfile index 2bb87ad60f91..7aa0febe306e 100644 --- a/e2e/postgres.Dockerfile +++ b/e2e/postgres.Dockerfile @@ -1,3 +1,7 @@ +# Copyright (c) 2024 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + FROM postgres:16@sha256:3648b6c2ac30de803a598afbaaef47851a6ee1795d74b4a5dcc09a22513b15c9 -COPY ./database/bfgd/scripts/*.sql /docker-entrypoint-initdb.d/ \ No newline at end of file +COPY ./database/bfgd/scripts/*.sql /docker-entrypoint-initdb.d/ diff --git a/e2e/prestate-proof.json b/e2e/prestate-proof.json new file mode 100755 index 000000000000..387612768a97 --- /dev/null +++ b/e2e/prestate-proof.json @@ -0,0 +1,2 @@ +{"step":0,"pre":"0x03b0ec84cdb7e22bbd6d672af9fb00893981f7c58bbd975780f61a5a56d2868c","post":"0x03e8cda2bf763e1256ad968fd79e9c71931fb0071d855ecc39cccaa8da3da0fd","state-data":"0x75273e201c1d8e569e20c7b08a3a658eb2fb4618afd1a8ef522154d3fd062ee7000000000000000000000000000000000000000000000000000000000000000000000000000b1d8c000b1d900000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000","proof-data":"0x23a500040802c767000000000802c75f0000000000000000000000003c01000b2421f0a800200008000000008fa40004240210960000000c0000003403e00008b05657b3e2e4cd4d368ee6e357a2f102eba77c4c7c3ec049f4c8c501b11cf9546bba9faa09a9174a8081ffe135e412b98375dc93c534ff7615e2afc423c3cd78e2854df7c59fb4bd0570065a65c7c781dec592c95787ed03d1198fc987d93dbf210d33767dfcee54dbf965615d7440791281a8866bfc6796007c1f8222ba4eefe0be599133230d74c2aae2ac60a31faa50eb3ce09b765d6004747cd58d257ff3ee87548fe9d4d2a588e029965e3da72ec0e8aee3ba45c7401d185a1d00bae0efd64588526d6764a444f3bee59cace31e31c07313186802cadd1539255e8c5fa8441d2a4ee6892ef075723e70faaede75a215d0a97b750e8a1bf4091ead74c7957dd8e1120a09ea6a6c1b80ce88bf25d12ffd0752c114ddd30214cbcc7c8c93e49de3c5e0f8c336680f53cb63c7ed7c5959f9bc0c53e6312a7840f74fd3eec79043112312914f726fbe2e60440192c86564353c9e8d51bb34282c554a1b5b194906114f6f80bbe6e76b808b1d71eb45def92ab36ca5405a96478b5cbab750c10afd5f7ba73aebecf62de0f91524b8cd197552301fe2dbafcfbed1877e54df9bc6beb64c475f290a0586eab1d85082bb788d4dbb6e1f3a3aac4bec3321706c01643d85132a1421fef31e79cb91bbcaf2d6ff4b3ad826ea3dc8548978bfdf18af8fbd5d6029af2168d9c0cc876dafc9862603dc0cbc21608a0ace380b860a6e65b931195cd32a856d17d91fbc0dd9237612aa49e0a801f84af6403ce1aaba686a6e8942c041dafb253aefd056466ebca0c3d218e38d2de04edb023ed819feb0eb5a3e443d16291ec6fcbe5bc24d1f8878eba784aba7e38a4a519cd913338b6a7826c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} + diff --git a/go.mod b/go.mod index d787d2884b87..e0fd38a805fc 100644 --- a/go.mod +++ b/go.mod @@ -1,229 +1,86 @@ -module github.com/ethereum-optimism/optimism +module github.com/hemilabs/heminetwork -go 1.21.1 - -replace github.com/hemilabs/heminetwork => ./heminetwork +go 1.21 require ( - github.com/BurntSushi/toml v1.3.2 github.com/btcsuite/btcd v0.24.0 + github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 - github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231211205419-ff2e152c624f + github.com/docker/docker v25.0.5+incompatible + github.com/docker/go-connections v0.5.0 + github.com/dustin/go-humanize v1.0.1 github.com/ethereum/go-ethereum v1.13.5 - github.com/fsnotify/fsnotify v1.7.0 - github.com/go-chi/chi/v5 v5.0.10 - github.com/go-chi/docgen v1.2.0 - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb - github.com/google/go-cmp v0.6.0 - github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 - github.com/google/uuid v1.6.0 - github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/golang-lru/v2 v2.0.5 - github.com/hemilabs/heminetwork v0.0.0-00010101000000-000000000000 - github.com/holiman/uint256 v1.2.3 - github.com/ipfs/go-datastore v0.6.0 - github.com/ipfs/go-ds-leveldb v0.5.0 - github.com/jackc/pgtype v1.14.0 - github.com/jackc/pgx/v5 v5.5.0 - github.com/libp2p/go-libp2p v0.32.0 - github.com/libp2p/go-libp2p-mplex v0.9.0 - github.com/libp2p/go-libp2p-pubsub v0.10.0 - github.com/libp2p/go-libp2p-testing v0.12.0 - github.com/mattn/go-isatty v0.0.20 - github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.12.0 - github.com/multiformats/go-multiaddr-dns v0.3.1 - github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.30.0 - github.com/pkg/errors v0.9.1 - github.com/pkg/profile v1.7.0 + github.com/go-test/deep v1.1.0 + github.com/juju/loggo v1.0.0 + github.com/lib/pq v1.10.9 + github.com/mitchellh/go-homedir v1.1.0 + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/prometheus/client_golang v1.18.0 - github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.26.0 - golang.org/x/crypto v0.19.0 - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a - golang.org/x/sync v0.6.0 - golang.org/x/term v0.17.0 - golang.org/x/time v0.5.0 - gorm.io/driver/postgres v1.5.4 - gorm.io/gorm v1.25.5 + github.com/sethvargo/go-retry v0.2.4 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + github.com/testcontainers/testcontainers-go v0.28.0 + golang.org/x/sys v0.17.0 + nhooyr.io/websocket v1.8.10 ) require ( - github.com/DataDog/zstd v1.5.2 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/VictoriaMetrics/fastcache v1.12.1 // indirect - github.com/allegro/bigcache v1.2.1 // indirect - github.com/benbjohnson/clock v1.3.5 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.5 // indirect - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/cgroups v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/containerd/containerd v1.7.13 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect - github.com/deepmap/oapi-codegen v1.8.2 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/felixge/fgprof v0.9.3 // indirect - github.com/fjl/memsize v0.0.1 // indirect - github.com/flynn/noise v1.0.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b // indirect - github.com/getsentry/sentry-go v0.18.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/graph-gophers/graphql-go v1.3.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-bexpr v0.1.11 // indirect - github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect - github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect - github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/huin/goupnp v1.3.0 // indirect - github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect - github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect - github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/jackc/pgio v1.0.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/puddle/v2 v2.2.1 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/juju/loggo v1.0.0 // indirect - github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/holiman/uint256 v1.2.3 // indirect github.com/klauspost/compress v1.17.7 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-mplex v0.7.0 // indirect - github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.2.0 // indirect - github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.4.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.1 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/miekg/dns v1.1.56 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/pointerstructure v1.2.1 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.9.0 // indirect - github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-multistream v0.5.0 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect - github.com/naoina/go-stringutil v0.1.0 // indirect - github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect - github.com/onsi/ginkgo/v2 v2.13.0 // indirect - github.com/opencontainers/runtime-spec v1.1.0 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.4 // indirect - github.com/quic-go/quic-go v0.39.3 // indirect - github.com/quic-go/webtransport-go v0.6.0 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rivo/uniseg v0.4.3 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/rs/cors v1.9.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/supranational/blst v0.3.11 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/shirou/gopsutil/v3 v3.24.1 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect github.com/tklauser/numcpus v0.7.0 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.uber.org/automaxprocs v1.5.2 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.20.1 // indirect - go.uber.org/mock v0.3.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.1 // indirect + go.opentelemetry.io/otel/metric v1.23.1 // indirect + go.opentelemetry.io/otel/trace v1.23.1 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.18.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.2.1 // indirect - nhooyr.io/websocket v1.8.10 // indirect - rsc.io/tmplfunc v0.0.3 // indirect -) - -// Excludes to work around genproto conflicts between op-geth and heminetwork dependencies -exclude ( - google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514 - google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440 - google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 - google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 - google.golang.org/genproto v0.0.0-20180831171423-11092d34479b - google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 + golang.org/x/tools v0.18.1-0.20240311201521-78fbdeb61842 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) - -//replace github.com/ethereum/go-ethereum v1.13.5 => github.com/ethereum-optimism/op-geth v1.101304.2-0.20231130012434-cd5316814d08 - -//replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain -replace github.com/ethereum/go-ethereum v1.13.5 => ../op-geth diff --git a/go.sum b/go.sum index 8e1d83d80364..df0b9c07069b 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,16 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -61,66 +38,22 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -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/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= -github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= -github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -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/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0= -github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -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/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= +github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= @@ -128,110 +61,37 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= -github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= -github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE= +github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= -github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231211205419-ff2e152c624f h1:ISd3MAco0U0XT5ADDQ8pzVntQpL9yEUQzpsIqfLJY2M= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231211205419-ff2e152c624f/go.mod h1:/70H/KqrtKcvWvNGVj6S3rAcLC+kUPr3t2aDmYIS+Xk= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= -github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= -github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= +github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b h1:vMT47RYsrftsHSTQhqXwC3BYflo38OLC3Y4LtXtLyU0= -github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b/go.mod h1:CDncRYVRSDqwakm282WEkjfaAj1hxU/v5RXxk5nXOiI= -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/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/docgen v1.2.0 h1:da0Nq2PKU9W9pSOTUfVrKI1vIgTGpauo9cfh4Iwivek= -github.com/go-chi/docgen v1.2.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI= -github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -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-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -239,724 +99,221 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/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/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 h1:Ep/joEub9YwcjRY6ND3+Y/w0ncE540RtGatVhtZL0/Q= -github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= -github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= -github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= -github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= -github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= -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/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= -github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= -github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= -github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= -github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= -github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= -github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= -github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530 h1:dUJ578zuPEsXjtzOfEF0q9zDAfljJ9oFnTHcQaNkccw= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= -github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw= -github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -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/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= -github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= -github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0= github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 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/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -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/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM= -github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c= -github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= -github.com/libp2p/go-libp2p-mplex v0.9.0 h1:R58pDRAmuBXkYugbSSXR9wrTX3+1pFM1xP2bLuodIq8= -github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbNp0QwnUXM+P64Og= -github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= -github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= -github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= -github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= -github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= -github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= -github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= -github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/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/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= -github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= -github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= -github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= -github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= -github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= -github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -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/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.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= -github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= -github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= 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/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg= -github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= -github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY= -github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= -github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= +github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +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/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= +github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= -github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= -go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= -go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= +go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= +go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= +go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/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-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.18.1-0.20240311201521-78fbdeb61842 h1:No0LMXYFkp3j4oEsPdtY8LUQz33gu79Rm9DE+izMeGQ= +golang.org/x/tools v0.18.1-0.20240311201521-78fbdeb61842/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= 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-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-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -965,47 +322,24 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.4/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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= -gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/hemi/electrumx/conn.go b/hemi/electrumx/conn.go new file mode 100644 index 000000000000..532d2795d93c --- /dev/null +++ b/hemi/electrumx/conn.go @@ -0,0 +1,183 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package electrumx + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "sync" + "time" +) + +const ( + connPingInterval = 5 * time.Minute + connPingTimeout = 5 * time.Second +) + +// clientConn is a connection with an ElectrumX server. +type clientConn struct { + mx sync.Mutex + + conn net.Conn + requestID uint64 + + closeCh chan struct{} + onClose func(c *clientConn) +} + +// newClientConn returns a new clientConn. +func newClientConn(conn net.Conn, onClose func(c *clientConn)) *clientConn { + c := &clientConn{ + conn: conn, + closeCh: make(chan struct{}), + onClose: onClose, + } + go c.pinger() + return c +} + +// call writes a request to the server and reads the response. +func (c *clientConn) call(ctx context.Context, method string, params, result any) error { + log.Tracef("call") + defer log.Tracef("call exit") + + c.mx.Lock() + defer c.mx.Unlock() + c.requestID++ + + req := NewJSONRPCRequest(c.requestID, method, params) + if err := writeRequest(ctx, c.conn, req); err != nil { + return fmt.Errorf("write request: %w", err) + } + + res, err := readResponse(ctx, c.conn, req.ID) + if err != nil { + var rpcErr RPCError + if errors.As(err, &rpcErr) { + return rpcErr + } + return fmt.Errorf("read response: %w", err) + } + + if result != nil { + if err = json.Unmarshal(res.Result, &result); err != nil { + return fmt.Errorf("unmarshal result: %w", err) + } + } + + return nil +} + +// writeRequest writes a request to the connection. +func writeRequest(_ context.Context, w io.Writer, req *JSONRPCRequest) error { + log.Tracef("writeRequest") + defer log.Tracef("writeRequest exit") + + b, err := json.Marshal(req) + if err != nil { + return fmt.Errorf("marshal request: %w", err) + } + b = append(b, byte('\n')) + + if _, err = io.Copy(w, bytes.NewReader(b)); err != nil { + return err + } + + return nil +} + +// readResponse reads a response from the connection. +func readResponse(ctx context.Context, r io.Reader, reqID uint64) (*JSONRPCResponse, error) { + log.Tracef("readResponse") + defer log.Tracef("readResponse exit") + + reader := bufio.NewReader(r) + b, err := reader.ReadBytes('\n') + if err != nil { + return nil, err + } + + var res JSONRPCResponse + if err = json.Unmarshal(b, &res); err != nil { + return nil, fmt.Errorf("unmarshal response: %w", err) + } + if res.Error != nil { + return nil, RPCError(res.Error.Message) + } + + if res.ID != reqID { + if res.ID == 0 { + // ElectrumX may have sent a request, ignore it and try again. + // TODO(joshuasing): We should probably handle incoming requests by + // having a separate goroutine that handles reading. + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + log.Debugf("Received a response from ElectrumX with ID 0, retrying read response...") + return readResponse(ctx, r, reqID) + } + return nil, fmt.Errorf("response ID differs from request ID (%d != %d)", res.ID, reqID) + } + + return &res, nil +} + +// ping writes a ping request to the connection. +func (c *clientConn) ping() error { + log.Tracef("ping") + defer log.Tracef("ping exit") + + ctx, cancel := context.WithTimeout(context.Background(), connPingTimeout) + defer cancel() + + if err := c.call(ctx, "server.ping", nil, nil); err != nil { + return err + } + + return nil +} + +// pinger pings each connection on a ticker. +func (c *clientConn) pinger() { + ticker := time.NewTicker(connPingInterval) + for { + select { + case <-c.closeCh: + return + case <-ticker.C: + log.Debugf("Pinging") + if err := c.ping(); err != nil { + if !errors.Is(err, net.ErrClosed) { + log.Errorf("An error occurred while pinging connection: %v", err) + } + _ = c.Close() + return + } + } + } +} + +// Close closes the connection. +func (c *clientConn) Close() error { + log.Tracef("Close") + defer log.Tracef("Close exit") + + c.mx.Lock() + defer c.mx.Unlock() + + if c.onClose != nil { + c.onClose(c) + } + close(c.closeCh) + return c.conn.Close() +} diff --git a/hemi/electrumx/conn_pool.go b/hemi/electrumx/conn_pool.go new file mode 100644 index 000000000000..9f73b02697ff --- /dev/null +++ b/hemi/electrumx/conn_pool.go @@ -0,0 +1,149 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package electrumx + +import ( + "errors" + "fmt" + "net" + "slices" + "sync" +) + +// connPool represents an ElectrumX connection pool. +type connPool struct { + network string + address string + dialer net.Dialer + + // max is the maximum number of connections this pool may hold. + max int + + // poolMx is a mutex used for pool. + poolMx sync.Mutex + + // pool is a queue used to store pooled connections. + // TODO(joshuasing): This is used as a basic queue, however there are much + // more performant queue implementations that could be used. + pool []*clientConn +} + +// newConnPool creates a new connection pool. +func newConnPool(network, address string, initial, max int) (*connPool, error) { + if initial > max { + return nil, errors.New("initial connections must be less than max connections") + } + + p := &connPool{ + network: network, + address: address, + max: max, + } + + // Add initial connections to the pool. + for i := 0; i < initial; i++ { + conn, err := p.newConn() + if err != nil { + return nil, fmt.Errorf("new initial connection: %w", err) + } + p.freeConn(conn) + } + + return p, nil +} + +// newConn creates a connection. +func (p *connPool) newConn() (*clientConn, error) { + log.Tracef("newConn") + defer log.Tracef("newConn exit") + + c, err := p.dialer.Dial(p.network, p.address) + if err != nil { + return nil, err + } + return newClientConn(c, p.onClose), nil +} + +// onClose removes a connection from the pool if found. +// This function is called by a connection when it is closed. +func (p *connPool) onClose(conn *clientConn) { + log.Tracef("onClose") + defer log.Tracef("onClose exit") + + p.poolMx.Lock() + // Remove the connection from the pool. + slices.DeleteFunc(p.pool, func(c *clientConn) bool { + return c == conn + }) + p.poolMx.Unlock() +} + +// acquireConn returns a connection from the pool. +// If there are no available connections, a new connection will be returned. +func (p *connPool) acquireConn() (*clientConn, error) { + log.Tracef("acquireConn") + defer log.Tracef("acquireConn exit") + + var c *clientConn + p.poolMx.Lock() + if len(p.pool) > 0 { + c, p.pool = p.pool[0], p.pool[1:] + } + p.poolMx.Unlock() + + if c == nil { + // The connection pool is empty, create a new connection. + var err error + if c, err = p.newConn(); err != nil { + return nil, fmt.Errorf("new connection: %w", err) + } + } + + return c, nil +} + +// freeConn returns a connection to the pool. +// Closed connections must not be returned. +func (p *connPool) freeConn(conn *clientConn) { + log.Tracef("freeConn") + defer log.Tracef("freeConn exit") + + if conn == nil { + return + } + + p.poolMx.Lock() + if len(p.pool) >= p.max { + p.poolMx.Unlock() + // The connection pool is full, close the connection. + _ = conn.Close() + return + } + + p.pool = append(p.pool, conn) + p.poolMx.Unlock() +} + +// size returns the number of connections in the pool. +func (p *connPool) size() int { + p.poolMx.Lock() + defer p.poolMx.Unlock() + return len(p.pool) +} + +// Close closes the connection pool and all stored connections. +func (p *connPool) Close() error { + p.poolMx.Lock() + pool := make([]*clientConn, len(p.pool)) + copy(pool, p.pool) + p.pool = nil + p.max = 0 + p.poolMx.Unlock() + + for _, c := range pool { + _ = c.Close() + } + return nil +} diff --git a/hemi/electrumx/conn_pool_test.go b/hemi/electrumx/conn_pool_test.go new file mode 100644 index 000000000000..91b43e35715d --- /dev/null +++ b/hemi/electrumx/conn_pool_test.go @@ -0,0 +1,114 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package electrumx + +import ( + "context" + "testing" + "time" +) + +func TestConnPool(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + server := createMockServer(t) + defer server.Close() + + pool, err := newConnPool("tcp", server.address, + clientInitialConnections, clientMaximumConnections) + if err != nil { + t.Fatalf("failed to create connPool: %v", err) + } + + // Ensure initial connections were added to the pool + if s := pool.size(); s != clientInitialConnections { + t.Errorf("pool size = %d, want %d", s, clientInitialConnections) + } + + // Ensure initial connections were established + for i := 0; i < clientInitialConnections; i++ { + select { + case s := <-server.stateCh: + if !s { + t.Errorf("unexpected disconnect") + } + case <-ctx.Done(): + t.Fatalf("waiting for initial connection %d: %v", i, ctx.Err()) + } + } + + // Add more connections to the pool to hit the maximum limit + for i := 0; i < clientMaximumConnections; i++ { + conn, err := pool.newConn() + if err != nil { + t.Errorf("new connection: %v", err) + } + pool.freeConn(conn) + } + + // Ensure pool does not contain more than the maximum number of connections + if s := pool.size(); s != clientMaximumConnections { + t.Errorf("pool size = %d, want %d", s, clientMaximumConnections) + } + + // Ensure extra connections were closed when returned to the pool + var newConnCount int + for i := 0; i < clientMaximumConnections+clientInitialConnections; i++ { + select { + case s := <-server.stateCh: + if !s { + newConnCount-- + continue + } + newConnCount++ + case <-ctx.Done(): + t.Fatalf("waiting for extra connections (%d): %v", i, ctx.Err()) + } + } + wantNewConnCount := clientMaximumConnections - clientInitialConnections + if newConnCount != wantNewConnCount { + t.Errorf("%d new connections, want %d", newConnCount, wantNewConnCount) + } + + // Acquire connections from the pool + poolSize := pool.size() + removeConns := 2 + for i := 0; i < removeConns; i++ { + conn, err := pool.acquireConn() + if err != nil { + t.Errorf("acquire connection: %v", err) + } + + _ = conn.Close() + select { + case <-server.stateCh: // remove close notification + case <-ctx.Done(): + t.Fatalf("remove close notification: %v", ctx.Err()) + } + } + + // Ensure connections were removed from the pool + if s := pool.size(); s != poolSize-removeConns { + t.Errorf("pool size = %d, want %d", s, poolSize-removeConns) + } + + poolSize = pool.size() + if err = pool.Close(); err != nil { + t.Errorf("failed to close pool: %v", err) + } + + // Ensure all connections were closed + for i := 0; i < poolSize; i++ { + select { + case s := <-server.stateCh: + if s { + t.Errorf("unexpected connection") + } + case <-ctx.Done(): + t.Fatalf("waiting for all connections to close (%d): %v", i, ctx.Err()) + } + } +} diff --git a/hemi/electrumx/conn_test.go b/hemi/electrumx/conn_test.go new file mode 100644 index 000000000000..95953c66aec7 --- /dev/null +++ b/hemi/electrumx/conn_test.go @@ -0,0 +1,305 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package electrumx + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "os" + "strings" + "sync" + "testing" + "time" + + "github.com/phayes/freeport" +) + +func TestClientConn(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + server := createMockServer(t) + defer server.Close() + + conn, err := net.Dial("tcp", server.address) + if err != nil { + t.Fatalf("failed to dial server: %v", err) + } + defer conn.Close() + + c := newClientConn(conn, nil) + + tests := []struct { + name string + method string + + wantErr bool + wantErrContains string + }{ + { + name: "ping", + method: "server.ping", + }, + { + name: "response id mismatch", + method: "test.mismatch.res-id", + wantErr: true, + wantErrContains: "response ID differs from request ID", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := c.call(ctx, tt.method, nil, nil) + switch { + case (err != nil) != tt.wantErr: + t.Errorf("call err = %v, want err %v", + err, tt.wantErr) + case err != nil && tt.wantErr: + if tt.wantErrContains != "" && !strings.Contains(err.Error(), tt.wantErrContains) { + t.Errorf("call err = %q, want contains %q", + err.Error(), tt.wantErrContains) + } + } + }) + } +} + +func TestWriteRequest(t *testing.T) { + tests := []struct { + name string + req *JSONRPCRequest + want string + }{ + { + name: "simple", + req: NewJSONRPCRequest(1, "test", nil), + want: "{\"jsonrpc\":\"2.0\",\"method\":\"test\",\"id\":1}\n", + }, + { + name: "with params", + req: NewJSONRPCRequest(2, "test", map[string]any{ + "test": true, + }), + want: "{\"jsonrpc\":\"2.0\",\"method\":\"test\",\"params\":{\"test\":true},\"id\":2}\n", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + if err := writeRequest(context.Background(), &buf, tt.req); err != nil { + t.Errorf("writeRequest() err = %v", err) + } + + if got := buf.String(); got != tt.want { + t.Errorf("writeRequest() wrote %s, want %s", got, tt.want) + } + }) + } +} + +func TestReadResponse(t *testing.T) { + tests := []struct { + name string + reqID uint64 + writeRes *JSONRPCResponse + want *JSONRPCResponse + wantErr bool + wantErrStr string + }{ + { + name: "simple", + reqID: 1, + writeRes: &JSONRPCResponse{ + JSONRPC: "2.0", + ID: 1, + }, + want: &JSONRPCResponse{ + JSONRPC: "2.0", + ID: 1, + }, + }, + { + name: "response id mismatch", + reqID: 3, + writeRes: &JSONRPCResponse{ + JSONRPC: "2.0", + ID: 1, + }, + wantErr: true, + wantErrStr: "response ID differs from request ID (1 != 3)", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, _ := json.Marshal(tt.writeRes) + buf := bytes.NewBuffer(b) + _ = buf.WriteByte('\n') + + res, err := readResponse(context.Background(), buf, tt.reqID) + switch { + case (err != nil) != tt.wantErr: + t.Errorf("readResponse() err = %v, want err %v", + err, tt.wantErr) + case err != nil && tt.wantErr: + if tt.wantErrStr != "" && err.Error() != tt.wantErrStr { + t.Errorf("readResponse() err = %q, want %q", + err.Error(), tt.wantErrStr) + } + } + + p, _ := json.Marshal(res) + want, _ := json.Marshal(tt.want) + if string(p) != string(want) { + t.Errorf("readResponse() res = %s, want %s", + string(p), string(want)) + } + }) + } +} + +type mockServer struct { + address string + ln net.Listener + stateCh chan bool + + stopCh chan struct{} + wg sync.WaitGroup +} + +func createMockServer(t *testing.T) *mockServer { + addr := createAddress() + + ln, err := net.Listen("tcp", addr) + if err != nil { + t.Fatal(err) + } + + s := &mockServer{ + address: addr, + ln: ln, + stateCh: make(chan bool, 25), + stopCh: make(chan struct{}, 1), + } + + s.wg.Add(1) + go func() { + defer s.wg.Done() + for { + select { + case <-s.stopCh: + return + default: + } + + conn, err := ln.Accept() + if err != nil { + continue + } + + s.wg.Add(1) + go s.handleConnection(t, conn) + } + }() + + return s +} + +func (s *mockServer) Close() { + close(s.stopCh) + _ = s.ln.Close() + s.wg.Wait() + close(s.stateCh) +} + +func (s *mockServer) handleConnection(t *testing.T, conn net.Conn) { + t.Logf("Handling connection: %s", conn.RemoteAddr()) + + select { + case s.stateCh <- true: + default: + } + + defer func() { + select { + case s.stateCh <- false: + default: + } + + _ = conn.Close() + s.wg.Done() + }() + + reader := bufio.NewReader(conn) + + for { + select { + case <-s.stopCh: + return + default: + } + + err := conn.SetReadDeadline(time.Now().Add(5 * time.Second)) + if err != nil { + t.Errorf("failed to set read deadline: %v", err) + return + } + + b, err := reader.ReadBytes('\n') + if err != nil { + if errors.Is(err, io.EOF) { + return + } + if errors.Is(err, os.ErrDeadlineExceeded) { + continue + } + t.Errorf("failed to read from connection: %v", err) + continue + } + + var req JSONRPCRequest + if err := json.Unmarshal(b, &req); err != nil { + t.Errorf("failed to unmarshal request: %v", err) + continue + } + + res := &JSONRPCResponse{} + + if req.Method == "server.ping" { + res.ID = req.ID + } + + if req.Method == "test.mismatch.res-id" { + res.ID = 0x4a6f73687561 + } + + if res.ID != 0 { + b, err = json.Marshal(res) + if err != nil { + t.Errorf("failed to marshal response: %v", err) + continue + } + b = append(b, '\n') + + _, err = io.Copy(conn, bytes.NewReader(b)) + if err != nil { + t.Errorf("failed to write response: %v", err) + } + } + } +} + +func createAddress() string { + port, err := freeport.GetFreePort() + if err != nil { + panic(fmt.Errorf("find free port: %v", err)) + } + return fmt.Sprintf("localhost:%d", port) +} diff --git a/hemi/electrumx/electrumx.go b/hemi/electrumx/electrumx.go index 2e9ed23f22ad..3c70c22d1cdc 100644 --- a/hemi/electrumx/electrumx.go +++ b/hemi/electrumx/electrumx.go @@ -5,19 +5,18 @@ package electrumx import ( - "bufio" - "bytes" "context" "encoding/hex" "encoding/json" "errors" "fmt" - "io" "net" "strings" - "sync" + "time" btcchainhash "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/juju/loggo" + "github.com/sethvargo/go-retry" "github.com/hemilabs/heminetwork/bitcoin" ) @@ -36,6 +35,22 @@ type JSONRPCRequest struct { ID uint64 `json:"id"` } +// NewJSONRPCRequest creates a new JSONRPCRequest. +func NewJSONRPCRequest(id uint64, method string, params any) *JSONRPCRequest { + req := &JSONRPCRequest{ + JSONRPC: "2.0", + Method: method, + ID: id, + } + if params != nil { + b, err := json.Marshal(params) + if err != nil { + } + req.Params = b + } + return req +} + type JSONRPCResponse struct { JSONRPC string `json:"jsonrpc"` Error *JSONRPCError `json:"error,omitempty"` @@ -102,71 +117,65 @@ var ( // Client implements an electrumx JSON RPC client. type Client struct { - address string - id uint64 - mtx sync.Mutex + connPool *connPool } +var log = loggo.GetLogger("electrumx") + +const ( + clientInitialConnections = 2 + clientMaximumConnections = 5 +) + // NewClient returns an initialised electrumx client. func NewClient(address string) (*Client, error) { - return &Client{ - address: address, - }, nil -} + c := &Client{} -func (c *Client) call(ctx context.Context, method string, params, result any) error { - var dialer net.Dialer - conn, err := dialer.DialContext(ctx, "tcp", c.address) - if err != nil { - return fmt.Errorf("failed to dial electrumx: %v", err) + // The address may be empty during tests, ignore empty addresses. + if address != "" { + pool, err := newConnPool("tcp", address, + clientInitialConnections, clientMaximumConnections) + if err != nil { + return nil, fmt.Errorf("new connection pool: %w", err) + } + c.connPool = pool } - defer conn.Close() - c.mtx.Lock() - c.id++ - id := c.id - c.mtx.Unlock() + return c, nil +} - req := &JSONRPCRequest{ - JSONRPC: "2.0", - Method: method, - ID: id, +func (c *Client) call(ctx context.Context, method string, params, result any) error { + if c.connPool == nil { + // connPool may be nil if the address given to NewClient is empty. + return errors.New("connPool is nil") } - if params != any(nil) { - b, err := json.Marshal(params) + + backoff := retry.WithJitter(250*time.Millisecond, + retry.WithMaxRetries(5, retry.NewExponential(100*time.Millisecond))) + return retry.Do(ctx, backoff, func(ctx context.Context) error { + conn, err := c.connPool.acquireConn() if err != nil { + return retry.RetryableError(fmt.Errorf("acquire connection: %w", err)) } - req.Params = b - } - b, err := json.Marshal(req) - if err != nil { - return fmt.Errorf("failed to marshal request: %v", err) - } - b = append(b, byte('\n')) - if _, err := io.Copy(conn, bytes.NewReader(b)); err != nil { - return fmt.Errorf("failed to write request: %v", err) - } - reader := bufio.NewReader(conn) - b, err = reader.ReadBytes('\n') - if err != nil { - return fmt.Errorf("failed to read response: %v", err) - } + if err = conn.call(ctx, method, params, result); err != nil { + if errors.Is(err, net.ErrClosed) { + return retry.RetryableError(err) + } + c.connPool.freeConn(conn) + return err + } - var resp JSONRPCResponse - if err := json.Unmarshal(b, &resp); err != nil { - return fmt.Errorf("failed to unmarshal response: %v", err) - } - if resp.ID != req.ID { - return fmt.Errorf("response ID differs from request ID (%d != %d)", resp.ID, req.ID) - } - if resp.Error != nil { - return RPCError(resp.Error.Message) - } - if err := json.Unmarshal(resp.Result, &result); err != nil { - return fmt.Errorf("failed to unmarshal result: %v", err) - } + c.connPool.freeConn(conn) + return nil + }) +} +// Close closes the client. +func (c *Client) Close() error { + if c.connPool != nil { + return c.connPool.Close() + } return nil } @@ -197,7 +206,7 @@ type UTXO struct { func (c *Client) Balance(ctx context.Context, scriptHash []byte) (*Balance, error) { hash, err := btcchainhash.NewHash(scriptHash) if err != nil { - return nil, fmt.Errorf("invalid script hash: %v", err) + return nil, fmt.Errorf("invalid script hash: %w", err) } params := struct { ScriptHash string `json:"scripthash"` @@ -223,12 +232,17 @@ func (c *Client) Broadcast(ctx context.Context, rtx []byte) ([]byte, error) { } txHash, err := btcchainhash.NewHashFromStr(txHashStr) if err != nil { - return nil, fmt.Errorf("failed to decode transaction hash: %v", err) + return nil, fmt.Errorf("failed to decode transaction hash: %w", err) } return txHash[:], nil } func (c *Client) Height(ctx context.Context) (uint64, error) { + // TODO: The way this function is used could be improved. + // "blockchain.headers.subscribe" subscribes to receive notifications from + // the ElectrumX server, however this function appears to be used for + // polling instead, which could be replaced by handling the requests sent + // from the ElectrumX server. hn := &HeaderNotification{} if err := c.call(ctx, "blockchain.headers.subscribe", nil, hn); err != nil { return 0, err @@ -246,11 +260,11 @@ func (c *Client) RawBlockHeader(ctx context.Context, height uint64) (*bitcoin.Bl } var rbhStr string if err := c.call(ctx, "blockchain.block.header", ¶ms, &rbhStr); err != nil { - return nil, fmt.Errorf("failed to get block header: %v", err) + return nil, fmt.Errorf("failed to get block header: %w", err) } rbh, err := hex.DecodeString(rbhStr) if err != nil { - return nil, fmt.Errorf("failed to decode raw block header: %v", err) + return nil, fmt.Errorf("failed to decode raw block header: %w", err) } return bitcoin.RawBlockHeaderFromSlice(rbh) } @@ -258,7 +272,7 @@ func (c *Client) RawBlockHeader(ctx context.Context, height uint64) (*bitcoin.Bl func (c *Client) RawTransaction(ctx context.Context, txHash []byte) ([]byte, error) { hash, err := btcchainhash.NewHash(txHash) if err != nil { - return nil, fmt.Errorf("invalid transaction hash: %v", err) + return nil, fmt.Errorf("invalid transaction hash: %w", err) } params := struct { TXHash string `json:"tx_hash"` @@ -269,11 +283,11 @@ func (c *Client) RawTransaction(ctx context.Context, txHash []byte) ([]byte, err } var rtxStr string if err := c.call(ctx, "blockchain.transaction.get", ¶ms, &rtxStr); err != nil { - return nil, fmt.Errorf("failed to get transaction: %v", err) + return nil, fmt.Errorf("failed to get transaction: %w", err) } rtx, err := hex.DecodeString(rtxStr) if err != nil { - return nil, fmt.Errorf("failed to decode raw transaction: %v", err) + return nil, fmt.Errorf("failed to decode raw transaction: %w", err) } return rtx, nil } @@ -281,7 +295,7 @@ func (c *Client) RawTransaction(ctx context.Context, txHash []byte) ([]byte, err func (c *Client) Transaction(ctx context.Context, txHash []byte) ([]byte, error) { hash, err := btcchainhash.NewHash(txHash) if err != nil { - return nil, fmt.Errorf("invalid transaction hash: %v", err) + return nil, fmt.Errorf("invalid transaction hash: %w", err) } params := struct { TXHash string `json:"tx_hash"` @@ -292,9 +306,9 @@ func (c *Client) Transaction(ctx context.Context, txHash []byte) ([]byte, error) } var txJSON json.RawMessage if err := c.call(ctx, "blockchain.transaction.get", ¶ms, &txJSON); err != nil { - return nil, fmt.Errorf("failed to get transaction: %v", err) + return nil, fmt.Errorf("failed to get transaction: %w", err) } - return []byte(txJSON), nil + return txJSON, nil } func (c *Client) TransactionAtPosition(ctx context.Context, height, index uint64) ([]byte, []string, error) { @@ -317,12 +331,12 @@ func (c *Client) TransactionAtPosition(ctx context.Context, height, index uint64 } else if strings.HasPrefix(err.Error(), "db error: DBError('block ") && strings.Contains(err.Error(), " not on disk ") { return nil, nil, NewBlockNotOnDiskError(err) } - return nil, nil, fmt.Errorf("failed to get transaction from block: %v", err) + return nil, nil, fmt.Errorf("failed to get transaction from block: %w", err) } txHash, err := btcchainhash.NewHashFromStr(result.TXHash) if err != nil { - return nil, nil, fmt.Errorf("failed to decode transaction hash: %v", err) + return nil, nil, fmt.Errorf("failed to decode transaction hash: %w", err) } return txHash[:], result.Merkle, nil @@ -331,7 +345,7 @@ func (c *Client) TransactionAtPosition(ctx context.Context, height, index uint64 func (c *Client) UTXOs(ctx context.Context, scriptHash []byte) ([]*UTXO, error) { hash, err := btcchainhash.NewHash(scriptHash) if err != nil { - return nil, fmt.Errorf("invalid script hash: %v", err) + return nil, fmt.Errorf("invalid script hash: %w", err) } params := struct { ScriptHash string `json:"scripthash"` @@ -346,7 +360,7 @@ func (c *Client) UTXOs(ctx context.Context, scriptHash []byte) ([]*UTXO, error) for _, eutxo := range eutxos { hash, err := btcchainhash.NewHashFromStr(eutxo.Hash) if err != nil { - return nil, fmt.Errorf("failed to decode UTXO hash: %v", err) + return nil, fmt.Errorf("failed to decode UTXO hash: %w", err) } utxos = append(utxos, &UTXO{ Hash: hash[:], diff --git a/hemi/pop/pop.go b/hemi/pop/pop.go index c8957893a703..b574d5bc0bcf 100644 --- a/hemi/pop/pop.go +++ b/hemi/pop/pop.go @@ -23,7 +23,7 @@ type MinerAddress [20]byte func MinerAddressFromString(address string) (*MinerAddress, error) { b, err := hex.DecodeString(address) if err != nil { - return nil, fmt.Errorf("invalid miner address: %v", err) + return nil, fmt.Errorf("invalid miner address: %w", err) } var ma MinerAddress @@ -87,7 +87,7 @@ func ParseTransactionL2FromOpReturn(script []byte) (*TransactionL2, error) { } ksh, err := hemi.NewL2KeystoneAbrevFromBytes(data[4:]) if err != nil { - return nil, fmt.Errorf("failed to parse keystone header: %v", err) + return nil, fmt.Errorf("failed to parse keystone header: %w", err) } return &TransactionL2{L2Keystone: ksh}, nil } @@ -142,7 +142,7 @@ func ParseTransactionFromOpReturn(script []byte) (*Transaction, error) { } ksh, err := hemi.NewHeaderFromBytes(data[4:]) if err != nil { - return nil, fmt.Errorf("failed to parse keystone header: %v", err) + return nil, fmt.Errorf("failed to parse keystone header: %w", err) } return &Transaction{Keystone: ksh}, nil } diff --git a/license_header.txt b/license_header.txt new file mode 100644 index 000000000000..c57d4e25fc5a --- /dev/null +++ b/license_header.txt @@ -0,0 +1,3 @@ +Copyright (c) {{.Year}} {{.Holder}} +Use of this source code is governed by the MIT License, +which can be found in the LICENSE file. \ No newline at end of file diff --git a/service/bfg/bfg.go b/service/bfg/bfg.go index 305a145e0883..7dbc935c9436 100644 --- a/service/bfg/bfg.go +++ b/service/bfg/bfg.go @@ -62,40 +62,6 @@ func init() { loggo.ConfigureLoggers(logLevel) } -// InternalError is an error type to differentiates between caller and callee -// errors. An internal error is used whne something internal to the application -// fails. -type InternalError struct { - internal *protocol.Error - actual error -} - -// Err return the protocol.Error that can be sent over the wire. -func (ie InternalError) Err() *protocol.Error { - return ie.internal -} - -// String return the actual underlying error. -func (ie InternalError) String() string { - i := ie.internal - return fmt.Sprintf("%v [%v:%v]", ie.actual.Error(), i.Trace, i.Timestamp) -} - -// Error satifies the error interface. -func (ie InternalError) Error() string { - if ie.internal == nil { - return "internal error" - } - return ie.internal.String() -} - -func NewInternalErrorf(msg string, args ...interface{}) *InternalError { - return &InternalError{ - internal: protocol.Errorf("internal error"), - actual: fmt.Errorf(msg, args...), - } -} - func NewDefaultConfig() *Config { return &Config{ EXBTCAddress: "localhost:18001", @@ -127,6 +93,7 @@ type btcClient interface { Transaction(ctx context.Context, txHash []byte) ([]byte, error) TransactionAtPosition(ctx context.Context, height, index uint64) ([]byte, []string, error) UTXOs(ctx context.Context, scriptHash []byte) ([]*electrumx.UTXO, error) + Close() error } type Config struct { @@ -146,6 +113,11 @@ type Server struct { cfg *Config + // requests + requestLimit int // Request limiter queue depth + requestLimiter chan bool // Maximum in progress websocket commands + requestTimeout time.Duration + btcHeight uint64 hemiHeight uint32 @@ -185,12 +157,17 @@ func NewServer(cfg *Config) (*Server, error) { if cfg == nil { cfg = NewDefaultConfig() } + defaultRequestTimeout := 9 * time.Second // XXX + requestLimit := 1000 // XXX s := &Server{ - cfg: cfg, - popTXFinality: make(map[uint64][]*popTX), - btcHeight: cfg.BTCStartHeight, - server: http.NewServeMux(), - publicServer: http.NewServeMux(), + cfg: cfg, + requestLimiter: make(chan bool, requestLimit), + requestLimit: requestLimit, + requestTimeout: defaultRequestTimeout, + popTXFinality: make(map[uint64][]*popTX), + btcHeight: cfg.BTCStartHeight, + server: http.NewServeMux(), + publicServer: http.NewServeMux(), cmdsProcessed: prometheus.NewCounter(prometheus.CounterOpts{ Subsystem: promSubsystem, Name: "rpc_calls_total", @@ -198,11 +175,14 @@ func NewServer(cfg *Config) (*Server, error) { }), sessions: make(map[string]*bfgWs), } + for i := 0; i < requestLimit; i++ { + s.requestLimiter <- true + } var err error s.btcClient, err = electrumx.NewClient(cfg.EXBTCAddress) if err != nil { - return nil, fmt.Errorf("Failed to create electrumx client: %v", err) + return nil, fmt.Errorf("failed to create electrumx client: %w", err) } // We could use a PGURI verification here. @@ -210,88 +190,103 @@ func NewServer(cfg *Config) (*Server, error) { return s, nil } -func (s *Server) writeResponse(ctx context.Context, conn protocol.APIConn, response any, id string) error { - if err := bfgapi.Write(ctx, conn, id, response); err != nil { - log.Errorf("error occurred writing bfgapi: %s", err) - return err +// handleRequest is called as a go routine to handle a long lived command. +func (s *Server) handleRequest(parrentCtx context.Context, bws *bfgWs, wsid string, requestType string, handler func(ctx context.Context) (any, error)) { + log.Tracef("handleRequest: %v", bws.addr) + defer log.Tracef("handleRequest exit: %v", bws.addr) + + ctx, cancel := context.WithTimeout(parrentCtx, s.requestTimeout) + defer cancel() + + select { + case <-s.requestLimiter: + default: + log.Infof("Request limiter hit %v: %v", bws.addr, requestType) + <-s.requestLimiter } + defer func() { s.requestLimiter <- true }() - return nil -} + log.Tracef("Handling request %v: %v", bws.addr, requestType) -func (s *Server) handleBitcoinBalance(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - log.Tracef("handleBitcoinBalance") - defer log.Tracef("handleBitcoinBalance exit") - // Increade command count - defer s.cmdsProcessed.Inc() + response, err := handler(ctx) + if err != nil { + log.Errorf("Failed to handle %v request %v: %v", + requestType, bws.addr, err) + } + if response == nil { + return + } - br, ok := payload.(*bfgapi.BitcoinBalanceRequest) - if !ok { - return nil, fmt.Errorf("not BitcoinBalanceRequest: %T", br) + log.Debugf("Responding to %v request with %v", requestType, spew.Sdump(response)) + + if err := bfgapi.Write(ctx, bws.conn, wsid, response); err != nil { + log.Errorf("Failed to handle %v request: protocol write failed: %v", + requestType, err) } +} - bResp := &bfgapi.BitcoinBalanceResponse{} +func (s *Server) handleBitcoinBalance(ctx context.Context, bbr *bfgapi.BitcoinBalanceRequest) (any, error) { + log.Tracef("handleBitcoinBalance") + defer log.Tracef("handleBitcoinBalance exit") - balance, err := s.btcClient.Balance(ctx, br.ScriptHash) + balance, err := s.btcClient.Balance(ctx, bbr.ScriptHash) if err != nil { - ie := NewInternalErrorf("error getting bitcoin balance: %s", err) - log.Errorf(ie.actual.Error()) - bResp.Error = ie.internal - return bResp, nil + e := protocol.NewInternalErrorf("bitcoin balance: %w", err) + return &bfgapi.BitcoinBalanceResponse{ + Error: e.ProtocolError(), + }, e } - bResp.Confirmed = balance.Confirmed - bResp.Unconfirmed = balance.Unconfirmed - return bResp, nil + return &bfgapi.BitcoinBalanceResponse{ + Confirmed: balance.Confirmed, + Unconfirmed: balance.Unconfirmed, + }, nil } -func (s *Server) handleBitcoinBroadcast(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { +func (s *Server) handleBitcoinBroadcast(ctx context.Context, bbr *bfgapi.BitcoinBroadcastRequest) (any, error) { log.Tracef("handleBitcoinBroadcast") defer log.Tracef("handleBitcoinBroadcast exit") - // Increade command count - defer s.cmdsProcessed.Inc() - - bbr, ok := payload.(*bfgapi.BitcoinBroadcastRequest) - if !ok { - return nil, fmt.Errorf("not a BitcoinBroadcastRequest: %T", bbr) - } - - bbResp := &bfgapi.BitcoinBroadcastResponse{} rr := bytes.NewReader(bbr.Transaction) mb := wire.MsgTx{} if err := mb.Deserialize(rr); err != nil { - bbResp.Error = protocol.Errorf("failed to deserialized tx: %s", err) - return bbResp, nil + return &bfgapi.BitcoinBroadcastResponse{Error: protocol.RequestErrorf( + "failed to deserialize tx: %s", err, + )}, nil } - var tl2 *pop.TransactionL2 - var err error + var ( + tl2 *pop.TransactionL2 + err error + ) for _, v := range mb.TxOut { tl2, err = pop.ParseTransactionL2FromOpReturn(v.PkScript) - if err != nil { - log.Errorf(err.Error()) // handle real error below + if err == nil { + break // Found the pop transaction. } } + if tl2 == nil { - bbResp.Error = protocol.Errorf("could not find l2 keystone abbrev in btc tx") - return bbResp, nil + return &bfgapi.BitcoinBroadcastResponse{ + Error: protocol.RequestErrorf("could not find l2 keystone abbrev in btc tx"), + }, nil } publicKeyUncompressed, err := pop.ParsePublicKeyFromSignatureScript(mb.TxIn[0].SignatureScript) if err != nil { - bbResp.Error = protocol.Errorf("could not parse signature script: %s", err) - return bbResp, nil + return &bfgapi.BitcoinBroadcastResponse{ + Error: protocol.RequestErrorf("could not parse signature script: %v", err), + }, nil } - txHash, err := s.btcClient.Broadcast(context.TODO(), bbr.Transaction) + txHash, err := s.btcClient.Broadcast(ctx, bbr.Transaction) if err != nil { - ie := NewInternalErrorf("error broadcasting to bitcoin: %s", err) - log.Errorf(ie.actual.Error()) - bbResp.Error = ie.internal - return bbResp, nil + // This may not alwyas be an internal error. + e := protocol.NewInternalErrorf("broadcast tx: %w", err) + return &bfgapi.BitcoinBroadcastResponse{ + Error: e.ProtocolError(), + }, e } - bbResp.TXID = txHash if err := s.db.PopBasisInsertPopMFields(ctx, &bfgd.PopBasis{ BtcTxId: txHash, @@ -300,72 +295,57 @@ func (s *Server) handleBitcoinBroadcast(ctx context.Context, bws *bfgWs, payload L2KeystoneAbrevHash: tl2.L2Keystone.Hash(), }); err != nil { if errors.Is(err, database.ErrDuplicate) { - bbResp.Error = protocol.Errorf("pop_basis already exists") - return bbResp, nil + return &bfgapi.BitcoinBroadcastResponse{ + Error: protocol.RequestErrorf("pop basis already exists"), + }, nil } if errors.Is(err, database.ErrValidation) { - log.Errorf("invalid pop basis: %s", err) - bbResp.Error = protocol.Errorf("invalid pop_basis") - return bbResp, nil + e := protocol.NewInternalErrorf("invalid pop basis: %w", err) + return &bfgapi.BitcoinBroadcastResponse{ + Error: e.ProtocolError(), + }, e } - ie := NewInternalErrorf("error inserting pop basis: %s", err) - bbResp.Error = ie.internal - log.Errorf(ie.actual.Error()) - return bbResp, nil + e := protocol.NewInternalErrorf("insert pop basis: %w", err) + return &bfgapi.BitcoinBroadcastResponse{ + Error: e.ProtocolError(), + }, e } - return bbResp, nil + return &bfgapi.BitcoinBroadcastResponse{TXID: txHash}, nil } -func (s *Server) handleBitcoinInfo(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { +func (s *Server) handleBitcoinInfo(ctx context.Context, bir *bfgapi.BitcoinInfoRequest) (any, error) { log.Tracef("handleBitcoinInfo") defer log.Tracef("handleBitcoinInfo exit") - // Increade command count - defer s.cmdsProcessed.Inc() - - _, ok := payload.(*bfgapi.BitcoinInfoRequest) - if !ok { - return nil, fmt.Errorf("not a BitcoinInfoRequest %T", payload) - } - - biResp := &bfgapi.BitcoinInfoResponse{} height, err := s.btcClient.Height(ctx) if err != nil { - ie := NewInternalErrorf("error getting bitcoin height: %s", err) - log.Errorf(ie.actual.Error()) - biResp.Error = ie.internal - return biResp, nil + e := protocol.NewInternalErrorf("bitcoin height: %w", err) + return &bfgapi.BitcoinInfoResponse{ + Error: e.ProtocolError(), + }, e } - biResp.Height = height - return biResp, nil + return &bfgapi.BitcoinInfoResponse{ + Height: height, + }, nil } -func (s *Server) handleBitcoinUTXOs(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { +func (s *Server) handleBitcoinUTXOs(ctx context.Context, bur *bfgapi.BitcoinUTXOsRequest) (any, error) { log.Tracef("handleBitcoinUTXOs") defer log.Tracef("handleBitcoinUTXOs exit") - // Increade command count - defer s.cmdsProcessed.Inc() - - bur, ok := payload.(*bfgapi.BitcoinUTXOsRequest) - if !ok { - err := fmt.Errorf("not a BitcoinUTXOsRequest %T", payload) - log.Errorf(err.Error()) - return nil, err - } - buResp := &bfgapi.BitcoinUTXOsResponse{} - - utxos, err := s.btcClient.UTXOs(context.TODO(), bur.ScriptHash) + utxos, err := s.btcClient.UTXOs(ctx, bur.ScriptHash) if err != nil { - ie := NewInternalErrorf("error getting bitcoin utxos: %s", err) - log.Errorf(ie.actual.Error()) - buResp.Error = ie.internal - return buResp, nil + e := protocol.NewInternalErrorf("bitcoin utxos: %w", err) + return &bfgapi.BitcoinUTXOsResponse{ + Error: e.ProtocolError(), + }, e + } + buResp := bfgapi.BitcoinUTXOsResponse{} for _, utxo := range utxos { buResp.UTXOs = append(buResp.UTXOs, &bfgapi.BitcoinUTXO{ Hash: utxo.Hash, @@ -377,47 +357,42 @@ func (s *Server) handleBitcoinUTXOs(ctx context.Context, bws *bfgWs, payload any return buResp, nil } -func (s *Server) handleAccessPublicKeyCreateRequest(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { +func (s *Server) handleAccessPublicKeyCreateRequest(ctx context.Context, acpkc *bfgapi.AccessPublicKeyCreateRequest) (any, error) { log.Tracef("handleAccessPublicKeyCreateRequest") defer log.Tracef("handleAccessPublicKeyCreateRequest exit") - accessPublicKeyCreateRequest, ok := payload.(*bfgapi.AccessPublicKeyCreateRequest) - if !ok { - err := fmt.Errorf("incorrect type: %T", payload) - return nil, err - } - - response := &bfgapi.AccessPublicKeyCreateResponse{} - - publicKey, err := hex.DecodeString(accessPublicKeyCreateRequest.PublicKey) + publicKey, err := hex.DecodeString(acpkc.PublicKey) if err != nil { - response.Error = protocol.Errorf(err.Error()) - return response, nil + return &bfgapi.AccessPublicKeyCreateResponse{ + Error: protocol.RequestErrorf("public key decode: %v", err), + }, nil } if err := s.db.AccessPublicKeyInsert(ctx, &bfgd.AccessPublicKey{ PublicKey: publicKey, }); err != nil { if errors.Is(err, database.ErrDuplicate) { - response.Error = protocol.Errorf("public key already exists") - return response, nil + return &bfgapi.AccessPublicKeyCreateResponse{ + Error: protocol.RequestErrorf("public key already exists"), + }, nil } if errors.Is(err, database.ErrValidation) { - response.Error = protocol.Errorf("invalid access public key") - return response, nil + return &bfgapi.AccessPublicKeyCreateResponse{ + Error: protocol.RequestErrorf("invalid access public key"), + }, nil } - ie := NewInternalErrorf("error inserting access public key: %s", err) - response.Error = ie.internal - log.Errorf(ie.actual.Error()) - return response, nil + e := protocol.NewInternalErrorf("insert public key: %w", err) + return &bfgapi.AccessPublicKeyCreateResponse{ + Error: protocol.RequestErrorf("invalid access public key"), + }, e } - return response, nil + return &bfgapi.AccessPublicKeyCreateResponse{}, nil } -func (s *Server) handleAccessPublicKeyDelete(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { +func (s *Server) handleAccessPublicKeyDelete(ctx context.Context, payload any) (any, error) { log.Tracef("handleAccessPublicKeyDelete") defer log.Tracef("handleAccessPublicKeyDelete exit") @@ -426,32 +401,34 @@ func (s *Server) handleAccessPublicKeyDelete(ctx context.Context, bws *bfgWs, pa return nil, fmt.Errorf("incorrect type %T", payload) } - response := &bfgapi.AccessPublicKeyDeleteResponse{} - b, err := hex.DecodeString(accessPublicKeyDeleteRequest.PublicKey) if err != nil { - response.Error = protocol.Errorf(err.Error()) - return response, nil + return &bfgapi.AccessPublicKeyDeleteResponse{ + Error: protocol.RequestErrorf("public key decode: %v", err), + }, nil } if err := s.db.AccessPublicKeyDelete(ctx, &bfgd.AccessPublicKey{ PublicKey: b, }); err != nil { if errors.Is(err, database.ErrNotFound) { - response.Error = protocol.Errorf("public key not found") - return response, nil + // XXX not sure I like giving this information away. + return &bfgapi.AccessPublicKeyDeleteResponse{ + Error: protocol.RequestErrorf("public key not found"), + }, nil } - ie := NewInternalErrorf("error deleting access public key: %s", err) - response.Error = ie.internal - log.Errorf(ie.actual.Error()) - return response, nil + e := protocol.NewInternalErrorf("error deleting access public key: %w", + err) + return &bfgapi.AccessPublicKeyDeleteResponse{ + Error: e.ProtocolError(), + }, e } - return response, nil + return &bfgapi.AccessPublicKeyDeleteResponse{}, nil } func (s *Server) processBitcoinBlock(ctx context.Context, height uint64) error { - log.Infof("Processing Bitcoin block at height %d...", height) + log.Tracef("Processing Bitcoin block at height %d...", height) rbh, err := s.btcClient.RawBlockHeader(ctx, height) if err != nil { @@ -492,7 +469,7 @@ func (s *Server) processBitcoinBlock(ctx context.Context, height uint64) error { // in a block, so hopefully we've got them all... return nil } - return fmt.Errorf("failed to get transaction at position (height %v, index %v): %v", height, index, err) + return fmt.Errorf("failed to get transaction at position (height %v, index %v): %w", height, index, err) } txHashEncoded := hex.EncodeToString(txHash) @@ -515,7 +492,7 @@ func (s *Server) processBitcoinBlock(ctx context.Context, height uint64) error { rtx, err := s.btcClient.RawTransaction(ctx, txHash) if err != nil { - return fmt.Errorf("failed to get raw transaction with txid %x: %v", txHash, err) + return fmt.Errorf("failed to get raw transaction with txid %x: %w", txHash, err) } log.Infof("got raw transaction with txid %x", txHash) @@ -593,7 +570,7 @@ func (s *Server) processBitcoinBlock(ctx context.Context, height uint64) error { func (s *Server) processBitcoinBlocks(ctx context.Context, start, end uint64) error { for i := start; i <= end; i++ { if err := s.processBitcoinBlock(ctx, i); err != nil { - return fmt.Errorf("failed to process bitcoin block at height %d: %v", i, err) + return fmt.Errorf("failed to process bitcoin block at height %d: %w", i, err) } s.btcHeight = i } @@ -662,9 +639,6 @@ func (s *Server) handleWebsocketPrivateRead(ctx context.Context, bws *bfgWs) { log.Tracef("handleWebsocketPrivateRead: %v", bws.addr) defer log.Tracef("handleWebsocketPrivateRead exit: %v", bws.addr) - // Command completed - defer s.cmdsProcessed.Inc() - for { cmd, id, payload, err := bfgapi.Read(ctx, bws.conn) if err != nil { @@ -682,41 +656,63 @@ func (s *Server) handleWebsocketPrivateRead(ctx context.Context, bws *bfgWs) { log.Tracef("handleWebsocketRead read %v: %v %v %v", bws.addr, cmd, id, spew.Sdump(payload)) - var response any - switch cmd { case bfgapi.CmdPingRequest: - response, err = s.handlePing(ctx, bws, payload, id) + err = s.handlePingRequest(ctx, bws, payload, id) case bfgapi.CmdPopTxForL2BlockRequest: - response, err = s.handlePopTxForL2Block(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.PopTxsForL2BlockRequest) + return s.handlePopTxsForL2Block(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle pop for l2 block request", handler) case bfgapi.CmdNewL2KeystonesRequest: - response, err = s.handleNewL2Keystones(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.NewL2KeystonesRequest) + return s.handleNewL2Keystones(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle new l2 keystones request", handler) case bfgapi.CmdBTCFinalityByRecentKeystonesRequest: - response, err = s.handleBtcFinalityByRecentKeystonesRequest(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BTCFinalityByRecentKeystonesRequest) + return s.handleBtcFinalityByRecentKeystonesRequest(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle finality recent keystones request", handler) case bfgapi.CmdBTCFinalityByKeystonesRequest: - response, err = s.handleBtcFinalityByKeystonesRequest(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BTCFinalityByKeystonesRequest) + return s.handleBtcFinalityByKeystonesRequest(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle finality keystones request", handler) case bfgapi.CmdAccessPublicKeyCreateRequest: - response, err = s.handleAccessPublicKeyCreateRequest(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.AccessPublicKeyCreateRequest) + return s.handleAccessPublicKeyCreateRequest(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle access key create request", handler) case bfgapi.CmdAccessPublicKeyDeleteRequest: - response, err = s.handleAccessPublicKeyDelete(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.AccessPublicKeyDeleteRequest) + return s.handleAccessPublicKeyDelete(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle access key delete request", handler) default: err = fmt.Errorf("unknown command") } - // if there was an error, close the websocket, only do this if we - // can't continue + // If set, it is a terminal error. if err != nil { - log.Errorf("handleWebsocketPrivateRead error %v %v: %v", bws.addr, cmd, err) - bws.conn.CloseStatus(websocket.StatusProtocolError, - err.Error()) + log.Errorf("handleWebsocketRead %v %v %v: %v", + bws.addr, cmd, id, err) return - } else { - if err := s.writeResponse(ctx, bws.conn, response, id); err != nil { - bws.conn.CloseStatus(websocket.StatusProtocolError, err.Error()) - return - } } + s.cmdsProcessed.Inc() } } @@ -726,9 +722,6 @@ func (s *Server) handleWebsocketPublicRead(ctx context.Context, bws *bfgWs) { log.Tracef("handleWebsocketPublicRead: %v", bws.addr) defer log.Tracef("handleWebsocketPublicRead exit: %v", bws.addr) - // Command completed - defer s.cmdsProcessed.Inc() - for { cmd, id, payload, err := bfgapi.Read(ctx, bws.conn) if err != nil { @@ -742,37 +735,58 @@ func (s *Server) handleWebsocketPublicRead(ctx context.Context, bws *bfgWs) { return } - var response any - switch cmd { case bfgapi.CmdPingRequest: - response, err = s.handlePing(ctx, bws, payload, id) + // quick call + err = s.handlePingRequest(ctx, bws, payload, id) case bfgapi.CmdL2KeystonesRequest: - response, err = s.handleL2KeystonesRequest(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.L2KeystonesRequest) + return s.handleL2KeystonesRequest(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle l2 keystones request", handler) case bfgapi.CmdBitcoinBalanceRequest: - response, err = s.handleBitcoinBalance(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BitcoinBalanceRequest) + return s.handleBitcoinBalance(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle bitcoin balance request", handler) case bfgapi.CmdBitcoinBroadcastRequest: - response, err = s.handleBitcoinBroadcast(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BitcoinBroadcastRequest) + return s.handleBitcoinBroadcast(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle bitcoin broadcast request", handler) case bfgapi.CmdBitcoinInfoRequest: - response, err = s.handleBitcoinInfo(ctx, bws, payload, id) + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BitcoinInfoRequest) + return s.handleBitcoinInfo(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle bitcoin broadcast request", handler) case bfgapi.CmdBitcoinUTXOsRequest: - response, err = s.handleBitcoinUTXOs(ctx, bws, payload, id) + + handler := func(c context.Context) (any, error) { + msg := payload.(*bfgapi.BitcoinUTXOsRequest) + return s.handleBitcoinUTXOs(c, msg) + } + + go s.handleRequest(ctx, bws, id, "handle bitcoin utxos request", handler) default: err = fmt.Errorf("unknown command") } + // If set, it is a terminal error. if err != nil { - log.Errorf("handleWebsocketPublicRead %v %v: %v", bws.addr, cmd, err) - bws.conn.CloseStatus(websocket.StatusProtocolError, - err.Error()) + log.Errorf("handleWebsocketRead %v %v %v: %v", + bws.addr, cmd, id, err) return - } else { - if err := s.writeResponse(ctx, bws.conn, response, id); err != nil { - bws.conn.CloseStatus(websocket.StatusProtocolError, err.Error()) - return - } } + s.cmdsProcessed.Inc() } } @@ -800,21 +814,19 @@ func (s *Server) newSession(bws *bfgWs) (string, error) { } } -func (s *Server) killSession(id string, why websocket.StatusCode) { +func (s *Server) deleteSession(id string) { + log.Tracef("deleteSession") + defer log.Tracef("deleteSession exit") + s.mtx.Lock() - bws, ok := s.sessions[id] + _, ok := s.sessions[id] if ok { delete(s.sessions, id) } s.mtx.Unlock() if !ok { - log.Errorf("killSession: id not found in sessions %s", id) - } else { - if err := bws.conn.CloseStatus(why, ""); err != nil { - // XXX this is too noisy. - log.Debugf("session close %v: %v", id, err) - } + log.Errorf("deleteSession: id not found in sessions %s", id) } } @@ -833,6 +845,7 @@ func (s *Server) handleWebsocketPrivate(w http.ResponseWriter, r *http.Request) r.RemoteAddr, err) return } + defer conn.Close(websocket.StatusProtocolError, "") bws := &bfgWs{ addr: r.RemoteAddr, @@ -850,7 +863,7 @@ func (s *Server) handleWebsocketPrivate(w http.ResponseWriter, r *http.Request) } defer func() { - s.killSession(bws.sessionId, websocket.StatusNormalClosure) + s.deleteSession(bws.sessionId) }() bws.wg.Add(1) @@ -941,7 +954,7 @@ func (s *Server) handleWebsocketPublic(w http.ResponseWriter, r *http.Request) { return } defer func() { - s.killSession(bws.sessionId, websocket.StatusNormalClosure) + s.deleteSession(bws.sessionId) }() // Always ping, required by protocol. @@ -963,47 +976,45 @@ func (s *Server) handleWebsocketPublic(w http.ResponseWriter, r *http.Request) { bws.sessionId, r.RemoteAddr, bws.publicKey) } -func (s *Server) handlePing(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - log.Tracef("handlePing: %v", bws.addr) - defer log.Tracef("handlePing exit: %v", bws.addr) +func (s *Server) handlePingRequest(ctx context.Context, bws *bfgWs, payload any, id string) error { + log.Tracef("handlePingRequest: %v", bws.addr) + defer log.Tracef("handlePingRequest exit: %v", bws.addr) p, ok := payload.(*bfgapi.PingRequest) if !ok { - return nil, fmt.Errorf("handlePing invalid payload type: %T", payload) + return fmt.Errorf("handlePingRequest invalid payload type: %T", payload) } response := &bfgapi.PingResponse{ OriginTimestamp: p.Timestamp, Timestamp: time.Now().Unix(), } - return response, nil -} - -func (s *Server) handlePopTxForL2Block(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - log.Tracef("handlePopTxForL2Block: %v", bws.addr) - defer log.Tracef("handlePopTxForL2Block exit: %v", bws.addr) + log.Tracef("responding with %v", spew.Sdump(response)) - p, ok := payload.(*bfgapi.PopTxsForL2BlockRequest) - if !ok { - return nil, fmt.Errorf("handlePopTxForL2Block invalid payload type: %T", - payload) + if err := bfgapi.Write(ctx, bws.conn, id, response); err != nil { + return fmt.Errorf("handlePingRequest write: %v %v", + bws.addr, err) } + return nil +} - response := bfgapi.PopTxsForL2BlockResponse{} +func (s *Server) handlePopTxsForL2Block(ctx context.Context, ptl2 *bfgapi.PopTxsForL2BlockRequest) (any, error) { + log.Tracef("handlePopTxsForL2Block") + defer log.Tracef("handlePopTxsForL2Block exit") - hash := hemi.HashSerializedL2KeystoneAbrev(p.L2Block) + hash := hemi.HashSerializedL2KeystoneAbrev(ptl2.L2Block) var h [32]byte copy(h[:], hash) popTxs, err := s.db.PopBasisByL2KeystoneAbrevHash(ctx, h, true) if err != nil { - ie := NewInternalErrorf("error getting pop basis: %s", err) - response.Error = ie.internal - log.Errorf(ie.actual.Error()) - return response, nil + e := protocol.NewInternalErrorf("error getting pop basis: %w", err) + return &bfgapi.PopTxsForL2BlockResponse{ + Error: e.ProtocolError(), + }, e } + response := &bfgapi.PopTxsForL2BlockResponse{} response.PopTxs = make([]bfgapi.PopTx, 0, len(popTxs)) - for k := range popTxs { response.PopTxs = append(response.PopTxs, bfgapi.PopTx{ BtcTxId: api.ByteSlice(popTxs[k].BtcTxId), @@ -1020,57 +1031,46 @@ func (s *Server) handlePopTxForL2Block(ctx context.Context, bws *bfgWs, payload return response, nil } -func (s *Server) handleBtcFinalityByRecentKeystonesRequest(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - p, ok := payload.(*bfgapi.BTCFinalityByRecentKeystonesRequest) - if ok == false { - return nil, fmt.Errorf( - "handleBtcFinalityByRecentKeystonesRequest invalid payload type %T", - payload, - ) - } - - response := bfgapi.BTCFinalityByRecentKeystonesResponse{} +func (s *Server) handleBtcFinalityByRecentKeystonesRequest(ctx context.Context, bfrk *bfgapi.BTCFinalityByRecentKeystonesRequest) (any, error) { + log.Tracef("handleBtcFinalityByRecentKeystonesRequest") + defer log.Tracef("handleBtcFinalityByRecentKeystonesRequest exit") - finalities, err := s.db.L2BTCFinalityMostRecent(ctx, p.NumRecentKeystones) + finalities, err := s.db.L2BTCFinalityMostRecent(ctx, bfrk.NumRecentKeystones) if err != nil { - ie := NewInternalErrorf("error getting finality: %s", err) - response.Error = ie.internal - log.Errorf(ie.actual.Error()) - return response, nil + e := protocol.NewInternalErrorf("error getting finality: %w", err) + return &bfgapi.BTCFinalityByRecentKeystonesResponse{ + Error: e.ProtocolError(), + }, e } - apiFinalities := []hemi.L2BTCFinality{} - for _, finality := range finalities { + apiFinalities := make([]hemi.L2BTCFinality, 0, len(finalities)) + for k, finality := range finalities { apiFinality, err := hemi.L2BTCFinalityFromBfgd( &finality, finality.BTCTipHeight, finality.EffectiveHeight, ) if err != nil { - return nil, err + e := protocol.NewInternalErrorf("error getting finality (%v): %w", + k, err) + return &bfgapi.BTCFinalityByRecentKeystonesResponse{ + Error: e.ProtocolError(), + }, e } apiFinalities = append(apiFinalities, *apiFinality) } - response.L2BTCFinalities = apiFinalities - - return response, nil + return &bfgapi.BTCFinalityByRecentKeystonesResponse{ + L2BTCFinalities: apiFinalities, + }, nil } -func (s *Server) handleBtcFinalityByKeystonesRequest(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - p, ok := payload.(*bfgapi.BTCFinalityByKeystonesRequest) - if ok == false { - return nil, fmt.Errorf( - "handleBtcFinalityByKeystonesRequest invalid payload type %T", - payload, - ) - } - - response := bfgapi.BTCFinalityByKeystonesResponse{} +func (s *Server) handleBtcFinalityByKeystonesRequest(ctx context.Context, bfkr *bfgapi.BTCFinalityByKeystonesRequest) (any, error) { + log.Tracef("handleBtcFinalityByKeystonesRequest") + defer log.Tracef("handleBtcFinalityByKeystonesRequest exit") - l2KeystoneAbrevHashes := []database.ByteArray{} - - for _, l := range p.L2Keystones { + l2KeystoneAbrevHashes := make([]database.ByteArray, 0, len(bfkr.L2Keystones)) + for _, l := range bfkr.L2Keystones { a := hemi.L2KeystoneAbbreviate(l) l2KeystoneAbrevHashes = append(l2KeystoneAbrevHashes, a.Hash()) } @@ -1080,13 +1080,13 @@ func (s *Server) handleBtcFinalityByKeystonesRequest(ctx context.Context, bws *b l2KeystoneAbrevHashes, ) if err != nil { - ie := NewInternalErrorf("error getting l2 keystones: %s", err) - response.Error = ie.internal - log.Errorf(ie.actual.Error()) - return response, nil + e := protocol.NewInternalErrorf("l2 keystones: %w", err) + return &bfgapi.BTCFinalityByKeystonesResponse{ + Error: e.ProtocolError(), + }, e } - apiFinalities := []hemi.L2BTCFinality{} + apiFinalities := make([]hemi.L2BTCFinality, 0, len(finalities)) for _, finality := range finalities { apiFinality, err := hemi.L2BTCFinalityFromBfgd( &finality, @@ -1094,38 +1094,34 @@ func (s *Server) handleBtcFinalityByKeystonesRequest(ctx context.Context, bws *b finality.EffectiveHeight, ) if err != nil { - return nil, err + e := protocol.NewInternalErrorf("l2 btc finality: %w", err) + return &bfgapi.BTCFinalityByKeystonesResponse{ + Error: e.ProtocolError(), + }, e } apiFinalities = append(apiFinalities, *apiFinality) } - response.L2BTCFinalities = apiFinalities - - return response, nil + return &bfgapi.BTCFinalityByKeystonesResponse{ + L2BTCFinalities: apiFinalities, + }, nil } -func (s *Server) handleL2KeystonesRequest(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - p, ok := payload.(*bfgapi.L2KeystonesRequest) - if ok == false { - return nil, fmt.Errorf( - "handleL2KeystonesRequest invalid payload type %T", - payload, - ) - } - - gkhResp := &bfgapi.L2KeystonesResponse{} +func (s *Server) handleL2KeystonesRequest(ctx context.Context, l2kr *bfgapi.L2KeystonesRequest) (any, error) { + log.Tracef("handleL2KeystonesRequest") + defer log.Tracef("handleL2KeystonesRequest exit") - results, err := s.db.L2KeystonesMostRecentN(ctx, - uint32(p.NumL2Keystones)) + results, err := s.db.L2KeystonesMostRecentN(ctx, uint32(l2kr.NumL2Keystones)) if err != nil { - ie := NewInternalErrorf("error getting l2 keystones: %s", err) - gkhResp.Error = ie.internal - log.Errorf(ie.actual.Error()) - return gkhResp, nil + e := protocol.NewInternalErrorf("error getting l2 keystones: %w", err) + return &bfgapi.L2KeystonesResponse{ + Error: e.ProtocolError(), + }, e } + l2Keystones := make([]hemi.L2Keystone, 0, len(results)) for _, v := range results { - gkhResp.L2Keystones = append(gkhResp.L2Keystones, hemi.L2Keystone{ + l2Keystones = append(l2Keystones, hemi.L2Keystone{ Version: uint8(v.Version), L1BlockNumber: v.L1BlockNumber, L2BlockNumber: v.L2BlockNumber, @@ -1136,28 +1132,27 @@ func (s *Server) handleL2KeystonesRequest(ctx context.Context, bws *bfgWs, paylo }) } - return gkhResp, nil + return &bfgapi.L2KeystonesResponse{ + L2Keystones: l2Keystones, + }, nil } func writeNotificationResponse(bws *bfgWs, response any) { if err := bfgapi.Write(bws.requestContext, bws.conn, "", response); err != nil { - log.Errorf( - "handleBtcFinalityNotification write: %v %v", - bws.addr, - err, - ) + log.Errorf("handleBtcFinalityNotification write: %v %v", bws.addr, err) } } func (s *Server) handleBtcFinalityNotification() error { - response := bfgapi.BTCFinalityNotification{} + log.Tracef("handleBtcFinalityNotification") + defer log.Tracef("handleBtcFinalityNotification exit") s.mtx.Lock() for _, bws := range s.sessions { if _, ok := bws.notify[notifyBtcFinalities]; !ok { continue } - go writeNotificationResponse(bws, response) + go writeNotificationResponse(bws, &bfgapi.BTCFinalityNotification{}) } s.mtx.Unlock() @@ -1165,14 +1160,15 @@ func (s *Server) handleBtcFinalityNotification() error { } func (s *Server) handleBtcBlockNotification() error { - response := bfgapi.BTCNewBlockNotification{} + log.Tracef("handleBtcBlockNotification") + defer log.Tracef("handleBtcBlockNotification exit") s.mtx.Lock() for _, bws := range s.sessions { if _, ok := bws.notify[notifyBtcBlocks]; !ok { continue } - go writeNotificationResponse(bws, response) + go writeNotificationResponse(bws, &bfgapi.BTCNewBlockNotification{}) } s.mtx.Unlock() @@ -1180,14 +1176,15 @@ func (s *Server) handleBtcBlockNotification() error { } func (s *Server) handleL2KeystonesNotification() error { - response := bfgapi.L2KeystonesNotification{} + log.Tracef("handleL2KeystonesNotification") + defer log.Tracef("handleL2KeystonesNotification exit") s.mtx.Lock() for _, bws := range s.sessions { if _, ok := bws.notify[notifyL2Keystones]; !ok { continue } - go writeNotificationResponse(bws, response) + go writeNotificationResponse(bws, &bfgapi.L2KeystonesNotification{}) } s.mtx.Unlock() @@ -1215,8 +1212,11 @@ func hemiL2KeystonesToDb(l2ks []hemi.L2Keystone) []bfgd.L2Keystone { return dbks } -func (s *Server) handleNewL2Keystones(ctx context.Context, bws *bfgWs, payload any, id string) (any, error) { - ks := hemiL2KeystonesToDb(payload.(*bfgapi.NewL2KeystonesRequest).L2Keystones) +func (s *Server) handleNewL2Keystones(ctx context.Context, nlkr *bfgapi.NewL2KeystonesRequest) (any, error) { + log.Tracef("handleNewL2Keystones") + defer log.Tracef("handleNewL2Keystones exit") + + ks := hemiL2KeystonesToDb(nlkr.L2Keystones) err := s.db.L2KeystonesInsert(ctx, ks) response := bfgapi.NewL2KeystonesResponse{} if err != nil { @@ -1306,8 +1306,6 @@ func (s *Server) handleAccessPublicKeys(table string, action string, payload, pa return } - // XXX this is racing with killSession but protected. We should - // create a killSessions that takes an encoded PublicKey s.mtx.Lock() for _, v := range s.sessions { // if public key does not exist on session, it's not an authenticated @@ -1320,8 +1318,7 @@ func (s *Server) handleAccessPublicKeys(table string, action string, payload, pa // encoding, ensure that the session string does for an equal comparison sessionPublicKeyEncoded := fmt.Sprintf("\\x%s", hex.EncodeToString(v.publicKey)) if sessionPublicKeyEncoded == accessPublicKey.PublicKeyEncoded { - sessionId := v.sessionId - go s.killSession(sessionId, protocol.StatusHandshakeErr) + v.conn.CloseStatus(websocket.StatusProtocolError, "killed") } } s.mtx.Unlock() @@ -1349,7 +1346,7 @@ func (s *Server) Run(pctx context.Context) error { var err error s.db, err = postgres.New(ctx, s.cfg.PgURI) if err != nil { - return fmt.Errorf("Failed to connect to database: %v", err) + return fmt.Errorf("failed to connect to database: %w", err) } defer s.db.Close() @@ -1455,7 +1452,7 @@ func (s *Server) Run(pctx context.Context) error { return fmt.Errorf("failed to create server: %w", err) } cs := []prometheus.Collector{ - s.cmdsProcessed, + s.cmdsProcessed, // XXX should we make two counters? priv/pub prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Subsystem: promSubsystem, Name: "running", @@ -1465,7 +1462,7 @@ func (s *Server) Run(pctx context.Context) error { s.wg.Add(1) go func() { defer s.wg.Done() - if err := d.Run(ctx, cs); err != context.Canceled { + if err := d.Run(ctx, cs); !errors.Is(err, context.Canceled) { log.Errorf("prometheus terminated with error: %v", err) return } @@ -1473,6 +1470,14 @@ func (s *Server) Run(pctx context.Context) error { }() } + defer func() { + if err := s.btcClient.Close(); err != nil { + log.Errorf("bitcoin client closed with error: %v", err) + return + } + log.Errorf("bitcoin client clean shutdown") + }() + s.wg.Add(1) go s.trackBitcoin(ctx) diff --git a/service/bfg/bfg_test.go b/service/bfg/bfg_test.go index baf69cf2cb65..d94e4f27d1d0 100644 --- a/service/bfg/bfg_test.go +++ b/service/bfg/bfg_test.go @@ -34,11 +34,11 @@ func checkBitcoinFinality(bf *BitcoinFinality) error { // Parse BTC block header and transaction. btcHeader := &btcwire.BlockHeader{} if err := btcHeader.Deserialize(bytes.NewReader(bf.BTCRawBlockHeader)); err != nil { - return fmt.Errorf("failed to deserialize BTC header: %v", err) + return fmt.Errorf("failed to deserialize BTC header: %w", err) } btcTransaction := &btcwire.MsgTx{} if err := btcTransaction.Deserialize(bytes.NewReader(bf.BTCRawTransaction)); err != nil { - return fmt.Errorf("failed to deserialize BTC transaction: %v", err) + return fmt.Errorf("failed to deserialize BTC transaction: %w", err) } btcTxHash := btcchainhash.DoubleHashB(bf.BTCRawTransaction) @@ -48,7 +48,7 @@ func checkBitcoinFinality(bf *BitcoinFinality) error { merkleHashes = append(merkleHashes, merkleHash) } if err := bitcoin.CheckMerkleChain(btcTxHash, bf.BTCTransactionIndex, merkleHashes, btcHeader.MerkleRoot[:]); err != nil { - return fmt.Errorf("failed to verify merkle path for transaction: %v", err) + return fmt.Errorf("failed to verify merkle path for transaction: %w", err) } // XXX - verify HEMI keystone header and PoP miner public key. diff --git a/service/bss/bss.go b/service/bss/bss.go index 002c2c2c740d..5ed24210b1a9 100644 --- a/service/bss/bss.go +++ b/service/bss/bss.go @@ -43,40 +43,6 @@ func init() { loggo.ConfigureLoggers(logLevel) } -// InternalError is an error type to differentiates between caller and callee -// errors. An internal error is used whne something internal to the application -// fails. -type InternalError struct { - internal *protocol.Error - actual error -} - -// Err return the protocol.Error that can be sent over the wire. -func (ie InternalError) Err() *protocol.Error { - return ie.internal -} - -// String return the actual underlying error. -func (ie InternalError) String() string { - i := ie.internal - return fmt.Sprintf("%v [%v:%v]", ie.actual.Error(), i.Trace, i.Timestamp) -} - -// Error satifies the error interface. -func (ie InternalError) Error() string { - if ie.internal == nil { - return "internal error" - } - return ie.internal.String() -} - -func NewInternalErrorf(msg string, args ...interface{}) *InternalError { - return &InternalError{ - internal: protocol.Errorf("internal error"), - actual: fmt.Errorf(msg, args...), - } -} - // Wrap for calling bfg commands type bfgCmd struct { msg any @@ -213,18 +179,8 @@ func (s *Server) handleRequest(parrentCtx context.Context, bws *bssWs, wsid stri response, err := handler(ctx) if err != nil { - // XXX these errors print an invalid trace for some reason. It - // mostly works but have a look at it and compare with client - // output and fix. - var ie *InternalError - if errors.As(err, &ie) { - log.Errorf("[INTERNAL ERROR] Failed to handle %v request %v: %v", - requestType, bws.addr, ie.String()) - } else { - // This may be too loud and can be silenced once in production. - log.Errorf("Failed to handle %v request %v: %v", - requestType, bws.addr, err) - } + log.Errorf("Failed to handle %v request %v: %v", + requestType, bws.addr, err) } if response == nil { return @@ -233,7 +189,8 @@ func (s *Server) handleRequest(parrentCtx context.Context, bws *bssWs, wsid stri log.Debugf("Responding to %v request with %v", requestType, spew.Sdump(response)) if err := bssapi.Write(ctx, bws.conn, wsid, response); err != nil { - log.Errorf("Failed to handle %v request: protocol write failed: %v", requestType, err) + log.Errorf("Failed to handle %v request: protocol write failed: %v", + requestType, err) } } @@ -271,56 +228,51 @@ func (s *Server) handlePopPayoutsRequest(ctx context.Context, msg *bssapi.PopPay log.Tracef("handlePopPayoutsRequest") defer log.Tracef("handlePopPayoutsRequest exit") - popTxsForL2BlockRequest := bfgapi.PopTxsForL2BlockRequest{ + popTxsForL2BlockRes, err := s.callBFG(ctx, bfgapi.PopTxsForL2BlockRequest{ L2Block: msg.L2BlockForPayout, - } - - popTxsForL2BlockRes, err := s.callBFG(ctx, &popTxsForL2BlockRequest) + }) if err != nil { + e := protocol.NewInternalErrorf("pop tx for l2: block %w", err) return &bssapi.PopPayoutsResponse{ - Error: protocol.Errorf("%v", err), - }, err - } - - popPayouts := ConvertPopTxsToPopPayouts( - (popTxsForL2BlockRes.(*bfgapi.PopTxsForL2BlockResponse)).PopTxs, - ) - - popPayoutsResponse := bssapi.PopPayoutsResponse{ - PopPayouts: popPayouts, + Error: e.ProtocolError(), + }, e } - return &popPayoutsResponse, nil + return &bssapi.PopPayoutsResponse{ + PopPayouts: ConvertPopTxsToPopPayouts( + (popTxsForL2BlockRes.(*bfgapi.PopTxsForL2BlockResponse)).PopTxs, + ), + }, nil } func (s *Server) handleL2KeytoneRequest(ctx context.Context, msg *bssapi.L2KeystoneRequest) (*bssapi.L2KeystoneResponse, error) { log.Tracef("handleL2KeytoneRequest") defer log.Tracef("handleL2KeytoneRequest exit") - newKeystoneHeadersRequest := bfgapi.NewL2KeystonesRequest{ - L2Keystones: []hemi.L2Keystone{ - msg.L2Keystone, - }, - } - - resp := &bssapi.L2KeystoneResponse{} - _, err := s.callBFG(ctx, &newKeystoneHeadersRequest) + _, err := s.callBFG(ctx, &bfgapi.NewL2KeystonesRequest{ + L2Keystones: []hemi.L2Keystone{msg.L2Keystone}, + }) if err != nil { - resp.Error = protocol.Errorf("%v", err) + e := protocol.NewInternalErrorf("new l2 keytsones: %w", err) + return &bssapi.L2KeystoneResponse{ + Error: e.ProtocolError(), + }, e } - return resp, err + return &bssapi.L2KeystoneResponse{}, nil } func (s *Server) handleBtcFinalityByRecentKeystonesRequest(ctx context.Context, msg *bssapi.BTCFinalityByRecentKeystonesRequest) (*bssapi.BTCFinalityByRecentKeystonesResponse, error) { - request := bfgapi.BTCFinalityByRecentKeystonesRequest{ - NumRecentKeystones: msg.NumRecentKeystones, - } + log.Tracef("handleBtcFinalityByRecentKeystonesRequest") + defer log.Tracef("handleBtcFinalityByRecentKeystonesRequest exit") - response, err := s.callBFG(ctx, &request) + response, err := s.callBFG(ctx, &bfgapi.BTCFinalityByRecentKeystonesRequest{ + NumRecentKeystones: msg.NumRecentKeystones, + }) if err != nil { + e := protocol.NewInternalErrorf("btc finality recent: %w", err) return &bssapi.BTCFinalityByRecentKeystonesResponse{ - Error: protocol.Errorf("%v", err), + Error: e.ProtocolError(), }, err } @@ -330,14 +282,16 @@ func (s *Server) handleBtcFinalityByRecentKeystonesRequest(ctx context.Context, } func (s *Server) handleBtcFinalityByKeystonesRequest(ctx context.Context, msg *bssapi.BTCFinalityByKeystonesRequest) (*bssapi.BTCFinalityByKeystonesResponse, error) { - request := bfgapi.BTCFinalityByKeystonesRequest{ - L2Keystones: msg.L2Keystones, - } + log.Tracef("handleBtcFinalityByKeystonesRequest") + defer log.Tracef("handleBtcFinalityByKeystonesRequest exit") - response, err := s.callBFG(ctx, &request) + response, err := s.callBFG(ctx, &bfgapi.BTCFinalityByKeystonesRequest{ + L2Keystones: msg.L2Keystones, + }) if err != nil { + e := protocol.NewInternalErrorf("btc finality keystones: %w", err) return &bssapi.BTCFinalityByKeystonesResponse{ - Error: protocol.Errorf("%v", err), + Error: e.ProtocolError(), }, err } @@ -415,8 +369,6 @@ func (s *Server) handleWebsocketRead(ctx context.Context, bws *bssWs) { if err != nil { log.Errorf("handleWebsocketRead %v %v %v: %v", bws.addr, cmd, id, err) - bws.conn.CloseStatus(websocket.StatusProtocolError, - err.Error()) return } @@ -458,7 +410,6 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { defer func() { s.deleteSession(bws.sessionId) - conn.Close(websocket.StatusNormalClosure, "") // Force shutdown connection }() bws.wg.Add(1) @@ -508,11 +459,13 @@ func (s *Server) newSession(bws *bssWs) (string, error) { func (s *Server) deleteSession(id string) { s.mtx.Lock() - if _, ok := s.sessions[id]; !ok { - log.Errorf("id not found in sessions %s", id) - } + _, ok := s.sessions[id] delete(s.sessions, id) s.mtx.Unlock() + + if !ok { + log.Errorf("id not found in sessions %s", id) + } } func writeNotificationResponse(bws *bssWs, response any) { @@ -526,11 +479,9 @@ func writeNotificationResponse(bws *bssWs, response any) { } func (s *Server) handleBtcFinalityNotification() error { - response := bssapi.BTCFinalityNotification{} - s.mtx.Lock() for _, bws := range s.sessions { - go writeNotificationResponse(bws, response) + go writeNotificationResponse(bws, &bssapi.BTCFinalityNotification{}) } s.mtx.Unlock() @@ -538,11 +489,9 @@ func (s *Server) handleBtcFinalityNotification() error { } func (s *Server) handleBtcBlockNotification() error { - response := bssapi.BTCNewBlockNotification{} - s.mtx.Lock() for _, bws := range s.sessions { - go writeNotificationResponse(bws, response) + go writeNotificationResponse(bws, &bssapi.BTCNewBlockNotification{}) } s.mtx.Unlock() @@ -593,7 +542,7 @@ func (s *Server) handleBFGWebsocketReadUnauth(ctx context.Context, conn *protoco go s.handleBtcBlockNotification() default: log.Errorf("unknown command: %v", cmd) - return // XXX exit for now to cause a ruckus in the logs + return } } } @@ -652,17 +601,17 @@ func (s *Server) callBFG(parrentCtx context.Context, msg any) (any, error) { // attempt to send select { case <-ctx.Done(): - return nil, NewInternalErrorf("callBFG send context error: %v", + return nil, protocol.NewInternalErrorf("callBFG send context error: %w", ctx.Err()) case s.bfgCmdCh <- bc: default: - return nil, NewInternalErrorf("bfg command queue full") + return nil, protocol.NewInternalErrorf("bfg command queue full") } // Wait for response select { case <-ctx.Done(): - return nil, NewInternalErrorf("callBFG received context error: %v", + return nil, protocol.NewInternalErrorf("callBFG received context error: %w", ctx.Err()) case payload := <-bc.ch: if err, ok := payload.(error); ok { @@ -821,7 +770,7 @@ func (s *Server) Run(parrentCtx context.Context) error { s.wg.Add(1) go func() { defer s.wg.Done() - if err := d.Run(ctx, cs); err != context.Canceled { + if err := d.Run(ctx, cs); !errors.Is(err, context.Canceled) { log.Errorf("prometheus terminated with error: %v", err) return } diff --git a/service/deucalion/deucalion.go b/service/deucalion/deucalion.go index ed3ac2d91ebc..f024cc528c23 100644 --- a/service/deucalion/deucalion.go +++ b/service/deucalion/deucalion.go @@ -69,7 +69,7 @@ var ( func init() { if err := config.Parse(cm); err != nil { - panic(fmt.Errorf("could not parse config during init: %v", err)) + panic(fmt.Errorf("could not parse config during init: %w", err)) } if cfg.ListenAddress == "" { return @@ -81,7 +81,7 @@ func init() { ctx := context.Background() d, err := New(cfg) if err != nil { - panic(fmt.Errorf("failed to create server: %v", err)) + panic(fmt.Errorf("failed to create server: %w", err)) } go func() { if err = d.Run(ctx, nil); !errors.Is(err, context.Canceled) { diff --git a/service/popm/popm.go b/service/popm/popm.go index 3b2e37b87fc7..c6cb0c02369d 100644 --- a/service/popm/popm.go +++ b/service/popm/popm.go @@ -42,9 +42,15 @@ const ( logLevel = "INFO" promSubsystem = "popm_service" // Prometheus + + l2KeystonesMaxSize = 10 ) -var log = loggo.GetLogger("popm") +var ( + log = loggo.GetLogger("popm") + + l2KeystoneRetryTimeout = 15 * time.Second +) func init() { loggo.ConfigureLoggers(logLevel) @@ -65,6 +71,8 @@ type Config struct { LogLevel string PrometheusListenAddress string + + RetryMineThreshold uint } func NewDefaultConfig() *Config { @@ -79,6 +87,11 @@ type bfgCmd struct { ch chan any } +type L2KeystoneProcessingContainer struct { + l2Keystone hemi.L2Keystone + requiresProcessing bool +} + type Miner struct { mtx sync.RWMutex wg sync.WaitGroup @@ -94,13 +107,16 @@ type Miner struct { btcAddress *btcutil.AddressPubKeyHash lastKeystone *hemi.L2Keystone - keystoneCh chan *hemi.L2Keystone // Prometheus isRunning bool bfgWg sync.WaitGroup bfgCmdCh chan bfgCmd // commands to send to bfg + + mineNowCh chan struct{} + + l2Keystones map[string]L2KeystoneProcessingContainer } func NewMiner(cfg *Config) (*Miner, error) { @@ -110,10 +126,11 @@ func NewMiner(cfg *Config) (*Miner, error) { m := &Miner{ cfg: cfg, - keystoneCh: make(chan *hemi.L2Keystone, 3), bfgCmdCh: make(chan bfgCmd, 10), holdoffTimeout: 5 * time.Second, requestTimeout: 5 * time.Second, + mineNowCh: make(chan struct{}, 1), + l2Keystones: make(map[string]L2KeystoneProcessingContainer, l2KeystonesMaxSize), } switch strings.ToLower(cfg.BTCChainName) { @@ -151,6 +168,10 @@ func (m *Miner) bitcoinBalance(ctx context.Context, scriptHash []byte) (uint64, return 0, 0, fmt.Errorf("not a BitcoinBalanceResponse %T", res) } + if bResp.Error != nil { + return 0, 0, bResp.Error + } + return bResp.Confirmed, bResp.Unconfirmed, nil } @@ -168,6 +189,10 @@ func (m *Miner) bitcoinBroadcast(ctx context.Context, tx []byte) ([]byte, error) return nil, fmt.Errorf("not a bitcoin broadcast response %T", res) } + if bbResp.Error != nil { + return nil, bbResp.Error + } + return bbResp.TXID, nil } @@ -184,6 +209,10 @@ func (m *Miner) bitcoinHeight(ctx context.Context) (uint64, error) { return 0, fmt.Errorf("not a BitcoinIfnoResponse") } + if biResp.Error != nil { + return 0, biResp.Error + } + return biResp.Height, nil } @@ -202,6 +231,10 @@ func (m *Miner) bitcoinUTXOs(ctx context.Context, scriptHash []byte) ([]*bfgapi. return nil, fmt.Errorf("not a buResp %T", res) } + if buResp.Error != nil { + return nil, buResp.Error + } + return buResp.UTXOs, nil } @@ -246,7 +279,7 @@ func createTx(l2Keystone *hemi.L2Keystone, btcHeight uint64, utxo *bfgapi.Bitcoi popTx := pop.TransactionL2{L2Keystone: aks} popTxOpReturn, err := popTx.EncodeToOpReturn() if err != nil { - return nil, fmt.Errorf("failed to encode PoP transaction: %v", err) + return nil, fmt.Errorf("failed to encode PoP transaction: %w", err) } btx.TxOut = append(btx.TxOut, btcwire.NewTxOut(0, popTxOpReturn)) @@ -262,12 +295,12 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { btcHeight, err := m.bitcoinHeight(ctx) if err != nil { - return fmt.Errorf("failed to get Bitcoin height: %v", err) + return fmt.Errorf("failed to get Bitcoin height: %w", err) } payToScript, err := btctxscript.PayToAddrScript(m.btcAddress) if err != nil { - return fmt.Errorf("failed to get pay to address script: %v", err) + return fmt.Errorf("failed to get pay to address script: %w", err) } if len(payToScript) != 25 { return fmt.Errorf("incorrect length for pay to public key script (%d != 25)", len(payToScript)) @@ -282,7 +315,7 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { // Check balance. confirmed, unconfirmed, err := m.bitcoinBalance(ctx, scriptHash[:]) if err != nil { - return fmt.Errorf("failed to get Bitcoin balance: %v", err) + return fmt.Errorf("failed to get Bitcoin balance: %w", err) } log.Tracef("Bitcoin balance for miner is: %v confirmed, %v unconfirmed", confirmed, unconfirmed) @@ -290,7 +323,7 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { log.Tracef("Looking for UTXOs for script hash %v", scriptHash) utxos, err := m.bitcoinUTXOs(ctx, scriptHash[:]) if err != nil { - return fmt.Errorf("failed to get Bitcoin UTXOs: %v", err) + return fmt.Errorf("failed to get Bitcoin UTXOs: %w", err) } log.Tracef("Found %d UTXOs at Bitcoin height %d", len(utxos), btcHeight) @@ -301,7 +334,7 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { utxos, err = pickUTXOs(utxos, feeAmount) if err != nil { - return fmt.Errorf("failed to pick UTXOs: %v", err) + return fmt.Errorf("failed to pick UTXOs: %w", err) } if len(utxos) != 1 { @@ -323,7 +356,7 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { // broadcast tx var buf bytes.Buffer if err := btx.Serialize(&buf); err != nil { - return fmt.Errorf("failed to serialize Bitcoin transaction: %v", err) + return fmt.Errorf("failed to serialize Bitcoin transaction: %w", err) } txb := buf.Bytes() @@ -331,11 +364,11 @@ func (m *Miner) mineKeystone(ctx context.Context, ks *hemi.L2Keystone) error { txh, err := m.bitcoinBroadcast(ctx, txb) if err != nil { - return fmt.Errorf("failed to broadcast PoP transaction: %v", err) + return fmt.Errorf("failed to broadcast PoP transaction: %w", err) } txHash, err := btcchainhash.NewHash(txh) if err != nil { - return fmt.Errorf("failed to create BTC hash from transaction hash: %v", err) + return fmt.Errorf("failed to create BTC hash from transaction hash: %w", err) } log.Infof("Successfully broadcast PoP transaction to Bitcoin with TX hash %v", txHash) @@ -372,6 +405,10 @@ func (m *Miner) L2Keystones(ctx context.Context, count uint64) (*bfgapi.L2Keysto return nil, fmt.Errorf("not a L2KeystonesResponse: %T", res) } + if kr.Error != nil { + return nil, kr.Error + } + return kr, nil } @@ -395,6 +432,10 @@ func (m *Miner) BitcoinBalance(ctx context.Context, scriptHash string) (*bfgapi. return nil, fmt.Errorf("not a BitcoinBalanceResponse: %T", res) } + if br.Error != nil { + return nil, br.Error + } + return br, nil } @@ -409,6 +450,10 @@ func (m *Miner) BitcoinInfo(ctx context.Context) (*bfgapi.BitcoinInfoResponse, e return nil, fmt.Errorf("not a BitcoinInfoResponse: %T", res) } + if ir.Error != nil { + return nil, ir.Error + } + return ir, nil } @@ -432,27 +477,59 @@ func (m *Miner) BitcoinUTXOs(ctx context.Context, scriptHash string) (*bfgapi.Bi return nil, fmt.Errorf("not a BitcoinUTXOsResponse: %T", res) } + if ir.Error != nil { + return nil, ir.Error + } + return ir, nil } +func (m *Miner) mineKnownKeystones(ctx context.Context) { + copies := m.l2KeystonesForProcessing() + + for _, e := range copies { + serialized := hemi.L2KeystoneAbbreviate(e).Serialize() + key := hex.EncodeToString(serialized[:]) + + log.Infof("Received keystone for mining with height %v...", e.L2BlockNumber) + + err := m.mineKeystone(ctx, &e) + if err != nil { + log.Errorf("Failed to mine keystone: %v", err) + } + + m.mtx.Lock() + + if v, ok := m.l2Keystones[key]; ok { + // if there is an error, mark keystone as "requires processing" so + // potentially gets retried, otherwise set this to false to + // nothing tries to process it + v.requiresProcessing = err != nil + m.l2Keystones[key] = v + } + + m.mtx.Unlock() + } +} + func (m *Miner) mine(ctx context.Context) { defer m.wg.Done() for { select { case <-ctx.Done(): return - case ks := <-m.keystoneCh: - log.Tracef("Received new keystone header for mining with height %v...", ks.L2BlockNumber) - if err := m.mineKeystone(ctx, ks); err != nil { - log.Errorf("Failed to mine keystone: %v", err) - } + case <-m.mineNowCh: + go m.mineKnownKeystones(ctx) + case <-time.After(l2KeystoneRetryTimeout): + go m.mineKnownKeystones(ctx) } } } func (m *Miner) queueKeystoneForMining(keystone *hemi.L2Keystone) { + m.AddL2Keystone(*keystone) select { - case m.keystoneCh <- keystone: + case m.mineNowCh <- struct{}{}: default: } } @@ -486,6 +563,12 @@ func (m *Miner) processReceivedKeystones(ctx context.Context, l2Keystones []hemi m.lastKeystone = &tmp m.queueKeystoneForMining(&tmp) + } else if m.cfg.RetryMineThreshold > 0 && (m.lastKeystone.L2BlockNumber-kh.L2BlockNumber) <= uint32(m.cfg.RetryMineThreshold)*hemi.KeystoneHeaderPeriod { + log.Tracef("received keystone older than latest, but within threshold, will remine l2 block number = %d", kh.L2BlockNumber) + tmp := kh + m.queueKeystoneForMining(&tmp) + } else { + log.Warningf("refusing to mine keystone with height %d, highest received: %d", kh.L2BlockNumber, m.lastKeystone.L2BlockNumber) } } } @@ -542,6 +625,10 @@ func (m *Miner) checkForKeystones(ctx context.Context) error { return fmt.Errorf("not an L2KeystonesResponse") } + if ghkrResp.Error != nil { + return ghkrResp.Error + } + log.Tracef("Got response with %v keystones", len(ghkrResp.L2Keystones)) m.processReceivedKeystones(ctx, ghkrResp.L2Keystones) @@ -622,7 +709,7 @@ func (m *Miner) handleBFGWebsocketRead(ctx context.Context, conn *protocol.Conn) case <-time.After(m.holdoffTimeout): } // XXX this is too noisy - log.Errorf("Retrying connectiong to BFG") + log.Errorf("Retrying connecting to BFG") continue } switch cmd { @@ -785,3 +872,75 @@ func (m *Miner) Run(pctx context.Context) error { return err } + +func (m *Miner) AddL2Keystone(val hemi.L2Keystone) { + serialized := hemi.L2KeystoneAbbreviate(val).Serialize() + key := hex.EncodeToString(serialized[:]) + + toInsert := L2KeystoneProcessingContainer{ + l2Keystone: val, + requiresProcessing: true, + } + + m.mtx.Lock() + defer m.mtx.Unlock() + + // keystone already exists, no-op + if _, ok := m.l2Keystones[key]; ok { + return + } + + if len(m.l2Keystones) < l2KeystonesMaxSize { + m.l2Keystones[key] = toInsert + return + } + + var smallestL2BlockNumber uint32 + var smallestKey string + + for k, v := range m.l2Keystones { + if smallestL2BlockNumber == 0 || v.l2Keystone.L2BlockNumber < smallestL2BlockNumber { + smallestL2BlockNumber = v.l2Keystone.L2BlockNumber + smallestKey = k + } + } + + // do not insert an L2Keystone that is older than all of the ones already + // added + if val.L2BlockNumber < smallestL2BlockNumber { + return + } + + delete(m.l2Keystones, smallestKey) + + m.l2Keystones[key] = toInsert +} + +// l2KeystonesForProcessing creates copies of the l2 keystones, set them to +// "processing", then returns the copies with the newest first +func (m *Miner) l2KeystonesForProcessing() []hemi.L2Keystone { + copies := make([]hemi.L2Keystone, 0) + + m.mtx.Lock() + + for i, v := range m.l2Keystones { + // if we're currently processing, or we've already processed the keystone + // then don't process + if !v.requiresProcessing { + continue + } + + // since we're about to process, mark this as false so others don't + // process the same + v.requiresProcessing = false + m.l2Keystones[i] = v + copies = append(copies, v.l2Keystone) + } + m.mtx.Unlock() + + slices.SortFunc(copies, func(a, b hemi.L2Keystone) int { + return int(b.L2BlockNumber) - int(a.L2BlockNumber) + }) + + return copies +} diff --git a/service/popm/popm_test.go b/service/popm/popm_test.go index 3f31291859ad..78d7de757541 100644 --- a/service/popm/popm_test.go +++ b/service/popm/popm_test.go @@ -12,6 +12,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "slices" "testing" "time" @@ -138,7 +139,9 @@ func TestProcessReceivedKeystones(t *testing.T) { }, } - miner := Miner{} + miner := Miner{ + l2Keystones: make(map[string]L2KeystoneProcessingContainer), + } miner.processReceivedKeystones(context.Background(), firstBatchOfL2Keystones) diff := deep.Equal(*miner.lastKeystone, hemi.L2Keystone{ @@ -161,6 +164,126 @@ func TestProcessReceivedKeystones(t *testing.T) { } } +// TestProcessReceivedKeystonesSameL2BlockNumber ensures that we process +// an l2 keystone with the same l2 block number that we saw before if it +// has changed and less than threshold +func TestProcessReceivedKeystonesSameL2BlockNumber(t *testing.T) { + firstBatchOfL2Keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + { + L2BlockNumber: 6, + EPHash: []byte{6}, + }, + { + L2BlockNumber: 5, + EPHash: []byte{5}, + }, + { + L2BlockNumber: 4, + EPHash: []byte{4}, + }, + } + + secondBatchOfL2Keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{44}, + }, + } + + miner := Miner{ + l2Keystones: make(map[string]L2KeystoneProcessingContainer), + cfg: NewDefaultConfig(), + } + miner.cfg.RetryMineThreshold = 1 + + miner.processReceivedKeystones(context.Background(), firstBatchOfL2Keystones) + miner.processReceivedKeystones(context.Background(), secondBatchOfL2Keystones) + + for _, v := range append(firstBatchOfL2Keystones, secondBatchOfL2Keystones...) { + serialized := hemi.L2KeystoneAbbreviate(v).Serialize() + key := hex.EncodeToString(serialized[:]) + if diff := deep.Equal(miner.l2Keystones[key].l2Keystone, v); len(diff) > 0 { + t.Fatalf("unexpected diff: %s", diff) + } + + } +} + +// TestProcessReceivedKeystonesOverThreshold tests that we don't re-queue +// an l2 keystone that is beyond threshold config +func TestProcessReceivedKeystonesOverThreshold(t *testing.T) { + firstBatchOfL2Keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 300, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 301, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 302, + EPHash: []byte{1}, + }, + { + L2BlockNumber: 306, + EPHash: []byte{6}, + }, + { + L2BlockNumber: 320, + EPHash: []byte{5}, + }, + { + L2BlockNumber: 310, + EPHash: []byte{4}, + }, + } + + secondBatchOfL2Keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{44}, + }, + } + + miner := Miner{ + l2Keystones: make(map[string]L2KeystoneProcessingContainer), + cfg: NewDefaultConfig(), + } + miner.cfg.RetryMineThreshold = 1 + + miner.processReceivedKeystones(context.Background(), firstBatchOfL2Keystones) + miner.processReceivedKeystones(context.Background(), secondBatchOfL2Keystones) + + for _, v := range firstBatchOfL2Keystones { + serialized := hemi.L2KeystoneAbbreviate(v).Serialize() + key := hex.EncodeToString(serialized[:]) + if diff := deep.Equal(miner.l2Keystones[key].l2Keystone, v); len(diff) > 0 { + t.Fatalf("unexpected diff: %s", diff) + } + } + + for _, v := range secondBatchOfL2Keystones { + serialized := hemi.L2KeystoneAbbreviate(v).Serialize() + key := hex.EncodeToString(serialized[:]) + if _, ok := miner.l2Keystones[key]; ok { + t.Fatalf("should not have queued keystone") + } + } +} + func TestCreateTxVersion2(t *testing.T) { l2Keystone := hemi.L2Keystone{} @@ -496,23 +619,358 @@ func TestProcessReceivedInAscOrder(t *testing.T) { receivedKeystones := []hemi.L2Keystone{} - for { - select { - case l2Keystone := <-miner.keystoneCh: - receivedKeystones = append(receivedKeystones, *l2Keystone) - continue - default: - break - } - break + for _, c := range miner.l2KeystonesForProcessing() { + receivedKeystones = append(receivedKeystones, c) } + slices.Reverse(receivedKeystones) diff := deep.Equal(firstBatchOfL2Keystones, receivedKeystones) if len(diff) != 0 { t.Fatalf("received unexpected diff: %s", diff) } } +// TestProcessReceivedOnlyOnce ensures that we only process keystones once if +// no error +func TestProcessReceivedOnlyOnce(t *testing.T) { + keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + } + + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + miner.processReceivedKeystones(context.Background(), keystones) + + processedKeystonesFirstTime := 0 + for range miner.l2KeystonesForProcessing() { + processedKeystonesFirstTime++ + } + if processedKeystonesFirstTime != 3 { + t.Fatalf("should have processed 3 keystones, processed %d", processedKeystonesFirstTime) + } + + processedKeystonesSecondTime := 0 + for range miner.l2KeystonesForProcessing() { + processedKeystonesSecondTime++ + } + + if processedKeystonesSecondTime != 0 { + t.Fatal("should have only processed the keystones once") + } +} + +// TestProcessReceivedUntilError ensures that we retry until no error +func TestProcessReceivedOnlyOnceWithError(t *testing.T) { + keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + } + + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + miner.processReceivedKeystones(context.Background(), keystones) + + processedKeystonesFirstTime := 0 + for _, c := range miner.l2KeystonesForProcessing() { + processedKeystonesFirstTime++ + serialized := hemi.L2KeystoneAbbreviate(c).Serialize() + key := hex.EncodeToString(serialized[:]) + miner.mtx.Lock() + if v, ok := miner.l2Keystones[key]; ok { + v.requiresProcessing = true + miner.l2Keystones[key] = v + } + miner.mtx.Unlock() + } + if processedKeystonesFirstTime != 3 { + t.Fatalf("should have processed 3 keystones, processed %d", processedKeystonesFirstTime) + } + + processedKeystonesSecondTime := 0 + for range miner.l2KeystonesForProcessing() { + processedKeystonesSecondTime++ + } + + if processedKeystonesSecondTime != 3 { + t.Fatalf("should have processed 3 keystones, processed %d", processedKeystonesSecondTime) + } + + processedKeystonesThirdTime := 0 + for range miner.l2KeystonesForProcessing() { + processedKeystonesThirdTime++ + } + + if processedKeystonesThirdTime != 0 { + t.Fatal("keystones should have already been processed") + } +} + +// TestProcessReceivedNoDuplicates ensures that we don't queue a duplicate +func TestProcessReceivedNoDuplicates(t *testing.T) { + keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + } + + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + + receivedKeystones := []hemi.L2Keystone{} + + miner.processReceivedKeystones(context.Background(), keystones) + + for _, c := range miner.l2KeystonesForProcessing() { + receivedKeystones = append(receivedKeystones, c) + } + + slices.Reverse(keystones) + + diff := deep.Equal([]hemi.L2Keystone{ + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + }, receivedKeystones) + if len(diff) != 0 { + t.Fatalf("received unexpected diff: %s", diff) + } +} + +// TestProcessReceivedInAscOrder ensures that if we queue more than 10 keystones +// for mining, that we override the oldest +func TestProcessReceivedInAscOrderOverride(t *testing.T) { + keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 4, + EPHash: []byte{4}, + }, + { + L2BlockNumber: 5, + EPHash: []byte{5}, + }, + { + L2BlockNumber: 6, + EPHash: []byte{6}, + }, + { + L2BlockNumber: 7, + EPHash: []byte{7}, + }, + { + L2BlockNumber: 8, + EPHash: []byte{8}, + }, + { + L2BlockNumber: 9, + EPHash: []byte{9}, + }, + { + L2BlockNumber: 10, + EPHash: []byte{10}, + }, + { + L2BlockNumber: 11, + EPHash: []byte{11}, + }, + } + + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + + for _, keystone := range keystones { + miner.processReceivedKeystones(context.Background(), []hemi.L2Keystone{keystone}) + } + + receivedKeystones := []hemi.L2Keystone{} + + for _, c := range miner.l2KeystonesForProcessing() { + receivedKeystones = append(receivedKeystones, c) + } + + slices.Reverse(keystones) + + diff := deep.Equal(keystones[:10], receivedKeystones) + if len(diff) != 0 { + t.Fatalf("received unexpected diff: %s", diff) + } +} + +func TestProcesAllKeystonesIfAble(t *testing.T) { + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + + for i := uint32(1); i < 1000; i++ { + keystone := hemi.L2Keystone{ + L2BlockNumber: i, + EPHash: []byte{byte(i)}, + } + miner.processReceivedKeystones(context.Background(), []hemi.L2Keystone{keystone}) + for _, c := range miner.l2KeystonesForProcessing() { + diff := deep.Equal(c, keystone) + if len(diff) != 0 { + t.Fatalf("unexpected diff: %s", diff) + } + } + } +} + +// TestProcessReceivedInAscOrderNoInsertIfTooOld ensures that if the queue +// is full, and we try to insert a keystone that is older than every other +// keystone, we don't insert it +func TestProcessReceivedInAscOrderNoInsertIfTooOld(t *testing.T) { + keystones := []hemi.L2Keystone{ + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + { + L2BlockNumber: 2, + EPHash: []byte{2}, + }, + { + L2BlockNumber: 3, + EPHash: []byte{3}, + }, + { + L2BlockNumber: 4, + EPHash: []byte{4}, + }, + { + L2BlockNumber: 5, + EPHash: []byte{5}, + }, + { + L2BlockNumber: 6, + EPHash: []byte{6}, + }, + { + L2BlockNumber: 7, + EPHash: []byte{7}, + }, + { + L2BlockNumber: 8, + EPHash: []byte{8}, + }, + { + L2BlockNumber: 9, + EPHash: []byte{9}, + }, + { + L2BlockNumber: 10, + EPHash: []byte{10}, + }, + { + L2BlockNumber: 11, + EPHash: []byte{11}, + }, + } + + miner, err := NewMiner(&Config{ + BTCPrivateKey: "ebaaedce6af48a03bbfd25e8cd0364140ebaaedce6af48a03bbfd25e8cd03641", + BTCChainName: "testnet3", + }) + if err != nil { + t.Fatal(err) + } + + for _, keystone := range keystones { + miner.processReceivedKeystones(context.Background(), []hemi.L2Keystone{keystone}) + } + + // this one should be dropped + miner.processReceivedKeystones(context.Background(), []hemi.L2Keystone{ + { + L2BlockNumber: 1, + EPHash: []byte{1}, + }, + }) + + receivedKeystones := []hemi.L2Keystone{} + + for _, c := range miner.l2KeystonesForProcessing() { + receivedKeystones = append(receivedKeystones, c) + } + + slices.Reverse(keystones) + + diff := deep.Equal(keystones[:10], receivedKeystones) + if len(diff) != 0 { + t.Fatalf("received unexpected diff: %s", diff) + } +} + func TestConnectToBFGAndPerformMineWithAuth(t *testing.T) { privateKey, err := dcrsecp256k1.GeneratePrivateKey() if err != nil { @@ -523,7 +981,7 @@ func TestConnectToBFGAndPerformMineWithAuth(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - server, msgCh, cleanup := createMockBFG(ctx, t, []string{publicKey}) + server, msgCh, cleanup := createMockBFG(ctx, t, []string{publicKey}, false, 1) defer cleanup() go func() { @@ -537,7 +995,7 @@ func TestConnectToBFGAndPerformMineWithAuth(t *testing.T) { } err = miner.Run(ctx) - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { panic(err) } }() @@ -587,7 +1045,7 @@ func TestConnectToBFGAndPerformMine(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - server, msgCh, cleanup := createMockBFG(ctx, t, []string{}) + server, msgCh, cleanup := createMockBFG(ctx, t, []string{}, false, 1) defer cleanup() go func() { @@ -601,7 +1059,7 @@ func TestConnectToBFGAndPerformMine(t *testing.T) { } err = miner.Run(ctx) - if err != nil && err != context.Canceled { + if err != nil && !errors.Is(err, context.Canceled) { panic(err) } }() @@ -643,6 +1101,136 @@ func TestConnectToBFGAndPerformMine(t *testing.T) { } } +func TestConnectToBFGAndPerformMineMultiple(t *testing.T) { + privateKey, err := dcrsecp256k1.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + server, msgCh, cleanup := createMockBFG(ctx, t, []string{}, false, 2) + defer cleanup() + + go func() { + miner, err := NewMiner(&Config{ + BFGWSURL: server.URL + bfgapi.RouteWebsocketPublic, + BTCChainName: "testnet3", + BTCPrivateKey: hex.EncodeToString(privateKey.Serialize()), + }) + if err != nil { + panic(err) + } + + err = miner.Run(ctx) + if err != nil && !errors.Is(err, context.Canceled) { + panic(err) + } + }() + + // we can't guarantee order here, so test that we get all expected messages + // from popm within the timeout + + messagesReceived := make(map[string]int) + + messagesExpected := map[protocol.Command]int{ + EventConnected: 1, + bfgapi.CmdL2KeystonesRequest: 1, + bfgapi.CmdBitcoinInfoRequest: 2, + bfgapi.CmdBitcoinBalanceRequest: 2, + bfgapi.CmdBitcoinUTXOsRequest: 2, + bfgapi.CmdBitcoinBroadcastRequest: 2, + } + + for { + select { + case msg := <-msgCh: + t.Logf("received message %v", msg) + messagesReceived[msg]++ + case <-ctx.Done(): + if ctx.Err() != nil { + t.Fatal(ctx.Err()) + } + } + missing := false + for m := range messagesExpected { + message := fmt.Sprintf("%s", m) + if messagesReceived[message] != messagesExpected[m] { + t.Logf("still missing message %v, found %d want %d", m, messagesReceived[message], messagesExpected[m]) + missing = true + } + } + if missing == false { + break + } + } +} + +func TestConnectToBFGAndPerformMineALot(t *testing.T) { + privateKey, err := dcrsecp256k1.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + server, msgCh, cleanup := createMockBFG(ctx, t, []string{}, false, 100) + defer cleanup() + + go func() { + miner, err := NewMiner(&Config{ + BFGWSURL: server.URL + bfgapi.RouteWebsocketPublic, + BTCChainName: "testnet3", + BTCPrivateKey: hex.EncodeToString(privateKey.Serialize()), + }) + if err != nil { + panic(err) + } + + err = miner.Run(ctx) + if err != nil && !errors.Is(err, context.Canceled) { + panic(err) + } + }() + + // we can't guarantee order here, so test that we get all expected messages + // from popm within the timeout + + messagesReceived := make(map[string]int) + + messagesExpected := map[protocol.Command]int{ + EventConnected: 1, + bfgapi.CmdL2KeystonesRequest: 1, + bfgapi.CmdBitcoinInfoRequest: l2KeystonesMaxSize, + bfgapi.CmdBitcoinBalanceRequest: l2KeystonesMaxSize, + bfgapi.CmdBitcoinUTXOsRequest: l2KeystonesMaxSize, + bfgapi.CmdBitcoinBroadcastRequest: l2KeystonesMaxSize, + } + + for { + select { + case msg := <-msgCh: + t.Logf("received message %v", msg) + messagesReceived[msg]++ + case <-ctx.Done(): + if ctx.Err() != nil { + t.Fatal(ctx.Err()) + } + } + missing := false + for m := range messagesExpected { + message := fmt.Sprintf("%s", m) + if messagesReceived[message] < messagesExpected[m] { + t.Logf("still missing message %v, found %d want %d", m, messagesReceived[message], messagesExpected[m]) + missing = true + } + } + if missing == false { + break + } + } +} + func TestConnectToBFGAndPerformMineWithAuthError(t *testing.T) { privateKey, err := dcrsecp256k1.GeneratePrivateKey() if err != nil { @@ -651,7 +1239,7 @@ func TestConnectToBFGAndPerformMineWithAuthError(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - server, msgCh, cleanup := createMockBFG(ctx, t, []string{"incorrect"}) + server, msgCh, cleanup := createMockBFG(ctx, t, []string{"incorrect"}, false, 1) defer cleanup() miner, err := NewMiner(&Config{ @@ -683,7 +1271,7 @@ func TestConnectToBFGAndPerformMineWithAuthError(t *testing.T) { } } -func createMockBFG(ctx context.Context, t *testing.T, publicKeys []string) (*httptest.Server, chan string, func()) { +func createMockBFG(ctx context.Context, t *testing.T, publicKeys []string, keystoneMined bool, keystoneCount int) (*httptest.Server, chan string, func()) { msgCh := make(chan string) handler := func(w http.ResponseWriter, r *http.Request) { @@ -770,13 +1358,13 @@ func createMockBFG(ctx context.Context, t *testing.T, publicKeys []string) (*htt }() if command == bfgapi.CmdL2KeystonesRequest { - if err := bfgapi.Write(ctx, conn, id, bfgapi.L2KeystonesResponse{ - L2Keystones: []hemi.L2Keystone{ - { - L2BlockNumber: 100, - }, - }, - }); err != nil { + response := bfgapi.L2KeystonesResponse{} + for i := 0; i < keystoneCount; i++ { + response.L2Keystones = append(response.L2Keystones, hemi.L2Keystone{ + L2BlockNumber: uint32(100 + i), + }) + } + if err := bfgapi.Write(ctx, conn, id, response); err != nil { if !errors.Is(ctx.Err(), context.Canceled) { panic(err) } @@ -834,7 +1422,6 @@ func createMockBFG(ctx context.Context, t *testing.T, publicKeys []string) (*htt } } } - } } diff --git a/service/popm/prometheus.go b/service/popm/prometheus.go index 9c55db99bbc3..6fe741b087a4 100644 --- a/service/popm/prometheus.go +++ b/service/popm/prometheus.go @@ -8,6 +8,7 @@ package popm import ( "context" + "errors" "fmt" "github.com/prometheus/client_golang/prometheus" @@ -32,7 +33,7 @@ func (m *Miner) handlePrometheus(ctx context.Context) error { m.wg.Add(1) go func() { defer m.wg.Done() - if err := d.Run(ctx, cs); err != context.Canceled { + if err := d.Run(ctx, cs); !errors.Is(err, context.Canceled) { log.Errorf("prometheus terminated with error: %v", err) return } diff --git a/service/tbc/crawler.go b/service/tbc/crawler.go new file mode 100644 index 000000000000..3e2287dd6ad9 --- /dev/null +++ b/service/tbc/crawler.go @@ -0,0 +1,444 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "context" + "crypto/sha256" + "encoding/binary" + "errors" + "fmt" + "runtime" + "sync" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/dustin/go-humanize" + + "github.com/hemilabs/heminetwork/database" + "github.com/hemilabs/heminetwork/database/tbcd" +) + +var ( + UtxoIndexHeightKey = []byte("utxoindexheight") // last indexed utxo height key + TxIndexHeightKey = []byte("txindexheight") // last indexed tx height key +) + +func logMemStats() { + var mem runtime.MemStats + runtime.ReadMemStats(&mem) + + // Go memory statistics are hard to interpret but the following list is + // an aproximation: + // Alloc is currently allocated memory + // TotalAlloc is all memory allocated over time + // Sys is basicaly a peak memory use + log.Infof("Alloc = %v, TotalAlloc = %v, Sys = %v, NumGC = %v\n", + humanize.IBytes(mem.Alloc), + humanize.IBytes(mem.TotalAlloc), + humanize.IBytes(mem.Sys), + mem.NumGC) +} + +func processUtxos(cp *chaincfg.Params, txs []*btcutil.Tx, utxos map[tbcd.Outpoint]tbcd.CacheOutput) error { + for idx, tx := range txs { + for _, txIn := range tx.MsgTx().TxIn { + if idx == 0 { + // Skip coinbase inputs + continue + } + op := tbcd.NewOutpoint(txIn.PreviousOutPoint.Hash, + txIn.PreviousOutPoint.Index) + if utxo, ok := utxos[op]; ok && !utxo.IsDelete() { + delete(utxos, op) + continue + } + } + for outIndex, txOut := range tx.MsgTx().TxOut { + if txscript.IsUnspendable(txOut.PkScript) { + continue + } + utxos[tbcd.NewOutpoint(*tx.Hash(), uint32(outIndex))] = tbcd.NewCacheOutput( + sha256.Sum256(txOut.PkScript), + uint64(txOut.Value), + uint32(outIndex)) + } + } + // log.Infof("%v", spew.Sdump(utxos)) + return nil +} + +func (s *Server) fetchOP(ctx context.Context, w *sync.WaitGroup, op tbcd.Outpoint, utxos map[tbcd.Outpoint]tbcd.CacheOutput) { + defer w.Done() + + pkScript, err := s.db.ScriptHashByOutpoint(ctx, op) + if err != nil { + // This happens when a transaction is created and spent in the + // same block. + // XXX this is probably too loud but log for investigation and + // remove later. + log.Debugf("db missing pkscript: %v", op) + return + } + s.mtx.Lock() + utxos[op] = tbcd.NewDeleteCacheOutput(*pkScript, op.TxIndex()) + s.mtx.Unlock() +} + +func (s *Server) fixupCache(ctx context.Context, b *btcutil.Block, utxos map[tbcd.Outpoint]tbcd.CacheOutput) error { + w := new(sync.WaitGroup) + txs := b.Transactions() + for idx, tx := range txs { + for _, txIn := range tx.MsgTx().TxIn { + if idx == 0 { + // Skip coinbase inputs + continue + } + op := tbcd.NewOutpoint(txIn.PreviousOutPoint.Hash, + txIn.PreviousOutPoint.Index) + s.mtx.Lock() + if _, ok := utxos[op]; ok { + s.mtx.Unlock() + continue + } + s.mtx.Unlock() + + // utxo not found, retrieve pkscript from database. + w.Add(1) + go s.fetchOP(ctx, w, op, utxos) + } + } + + w.Wait() + + return nil +} + +func (s *Server) indexUtxosInBlocks(ctx context.Context, startHeight, maxHeight uint64, utxos map[tbcd.Outpoint]tbcd.CacheOutput) (int, error) { + log.Tracef("indexUtxoBlocks") + defer log.Tracef("indexUtxoBlocks exit") + + circuitBreaker := false + if maxHeight != 0 { + circuitBreaker = true + } + + utxosPercentage := 95 // flush cache at >95% capacity + blocksProcessed := 0 + for height := startHeight; ; height++ { + bhs, err := s.db.BlockHeadersByHeight(ctx, height) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + log.Infof("No more blocks at: %v", height) + break + } + return 0, fmt.Errorf("block headers by height %v: %v", height, err) + } + eb, err := s.db.BlockByHash(ctx, bhs[0].Hash) + if err != nil { + return 0, fmt.Errorf("block by hash %v: %v", height, err) + } + b, err := btcutil.NewBlockFromBytes(eb.Block) + if err != nil { + ch, _ := chainhash.NewHash(bhs[0].Hash) + return 0, fmt.Errorf("could not decode block %v %v: %v", + height, ch, err) + } + + // fixupCache is executed in parallel meaning that the utxos + // map must be locked as it is being processed. + err = s.fixupCache(ctx, b, utxos) + if err != nil { + return 0, fmt.Errorf("parse block %v: %v", height, err) + } + // At this point we can lockless since it is all single + // threaded again. + err = processUtxos(s.chainParams, b.Transactions(), utxos) + if err != nil { + return 0, fmt.Errorf("process utxos %v: %v", height, err) + } + + blocksProcessed++ + + // Try not to overshoot the cache to prevent costly allocations + cp := len(utxos) * 100 / s.cfg.MaxCachedTxs + if height%10000 == 0 || cp > utxosPercentage || blocksProcessed == 1 { + log.Infof("Utxo indexer height: %v utxo cache %v%%", height, cp) + } + if cp > utxosPercentage { + // Set utxosMax to the largest utxo capacity seen + s.cfg.MaxCachedTxs = max(len(utxos), s.cfg.MaxCachedTxs) + // Flush + break + } + + // If set we may have to exit early + if circuitBreaker { + if height >= maxHeight-1 { + break + } + } + } + + return blocksProcessed, nil +} + +func (s *Server) UtxoIndexer(ctx context.Context, height, count uint64) error { + log.Tracef("UtxoIndexer") + defer log.Tracef("UtxoIndexer exit") + + var maxHeight uint64 + circuitBreaker := false + if count != 0 { + circuitBreaker = true + maxHeight = height + count + } + + // Allocate here so that we don't waste space when not indexing. + utxos := make(map[tbcd.Outpoint]tbcd.CacheOutput, s.cfg.MaxCachedTxs) + defer clear(utxos) + + log.Infof("Start indexing UTxos at height %v count %v", height, count) + for { + start := time.Now() + blocksProcessed, err := s.indexUtxosInBlocks(ctx, height, maxHeight, utxos) + if err != nil { + return fmt.Errorf("index blocks: %w", err) + } + if blocksProcessed == 0 { + return nil + } + utxosCached := len(utxos) + log.Infof("Utxo indexer blocks processed %v in %v utxos cached %v cache unused %v avg tx/blk %v", + blocksProcessed, time.Now().Sub(start), utxosCached, + s.cfg.MaxCachedTxs-utxosCached, utxosCached/blocksProcessed) + + start = time.Now() + err = s.db.BlockUtxoUpdate(ctx, utxos) + if err != nil { + return fmt.Errorf("block tx update: %w", err) + } + // leveldb does all kinds of allocations, force GC to lower + // memory preassure. + logMemStats() + runtime.GC() + + log.Infof("Flushing utxos complete %v took %v", + utxosCached, time.Now().Sub(start)) + + height += uint64(blocksProcessed) + + // Record height in metadata + var dbHeight [8]byte + binary.BigEndian.PutUint64(dbHeight[:], height) + err = s.db.MetadataPut(ctx, UtxoIndexHeightKey, dbHeight[:]) + if err != nil { + return fmt.Errorf("metadata utxo height: %w", err) + } + + // If set we may have to exit early + if circuitBreaker { + log.Infof("Indexed utxos to height: %v", height-1) + if height >= maxHeight { + return nil + } + } + } +} + +func processTxs(cp *chaincfg.Params, blockHash *chainhash.Hash, txs []*btcutil.Tx, txsCache map[tbcd.TxKey]*tbcd.TxValue) error { + for _, tx := range txs { + // cache txid <-> block + txsCache[tbcd.NewTxMapping(tx.Hash(), blockHash)] = nil + + // cache spent transactions + for txInIdx, txIn := range tx.MsgTx().TxIn { + txk, txv := tbcd.NewTxSpent( + blockHash, + tx.Hash(), + &txIn.PreviousOutPoint.Hash, + txIn.PreviousOutPoint.Index, + uint32(txInIdx)) + txsCache[txk] = &txv + } + } + return nil +} + +func (s *Server) indexTxsInBlocks(ctx context.Context, startHeight, maxHeight uint64, txs map[tbcd.TxKey]*tbcd.TxValue) (int, error) { + log.Tracef("indexTxsInBlocks") + defer log.Tracef("indexTxsInBlocks exit") + + circuitBreaker := false + if maxHeight != 0 { + circuitBreaker = true + } + + txsPercentage := 95 // flush cache at >95% capacity + blocksProcessed := 0 + for height := startHeight; ; height++ { + bhs, err := s.db.BlockHeadersByHeight(ctx, height) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + log.Infof("No more blocks at: %v", height) + break + } + return 0, fmt.Errorf("block headers by height %v: %v", height, err) + } + eb, err := s.db.BlockByHash(ctx, bhs[0].Hash) + if err != nil { + return 0, fmt.Errorf("block by hash %v: %v", height, err) + } + b, err := btcutil.NewBlockFromBytes(eb.Block) + if err != nil { + ch, _ := chainhash.NewHash(bhs[0].Hash) + return 0, fmt.Errorf("could not decode block %v %v: %v", + height, ch, err) + } + + err = processTxs(s.chainParams, b.Hash(), b.Transactions(), txs) + if err != nil { + return 0, fmt.Errorf("process txs %v: %v", height, err) + } + + blocksProcessed++ + + // Try not to overshoot the cache to prevent costly allocations + cp := len(txs) * 100 / s.cfg.MaxCachedTxs + if height%10000 == 0 || cp > txsPercentage || blocksProcessed == 1 { + log.Infof("Tx indexer height: %v tx cache %v%%", height, cp) + } + if cp > txsPercentage { + // Set txsMax to the largest tx capacity seen + s.cfg.MaxCachedTxs = max(len(txs), s.cfg.MaxCachedTxs) + // Flush + break + } + + // If set we may have to exit early + if circuitBreaker { + if height >= maxHeight-1 { + break + } + } + } + + return blocksProcessed, nil +} + +// TxIndexer starts indexing at start height for count blocks. If count is 0 +// the indexers will index to tip. It does NOT verify that the provided start +// height is correct. This is the version of the function that has no training +// wheels and is meant for internal use only. +func (s *Server) TxIndexer(ctx context.Context, height, count uint64) error { + log.Tracef("TxIndexer") + defer log.Tracef("TxIndexer exit") + + var maxHeight uint64 + circuitBreaker := false + if count != 0 { + circuitBreaker = true + maxHeight = height + count + } + + // Allocate here so that we don't waste space when not indexing. + txs := make(map[tbcd.TxKey]*tbcd.TxValue, s.cfg.MaxCachedTxs) + // log.Infof("max %v %v", s.cfg.MaxCachedTxs, s.cfg.MaxCachedTxs*(105)) + // return nil + defer clear(txs) + + log.Infof("Start indexing transactions at height %v count %v", height, count) + for { + start := time.Now() + blocksProcessed, err := s.indexTxsInBlocks(ctx, height, maxHeight, txs) + if err != nil { + return fmt.Errorf("index blocks: %w", err) + } + if blocksProcessed == 0 { + return nil + } + txsCached := len(txs) + log.Infof("Tx indexer blocks processed %v in %v transactions cached %v cache unused %v avg tx/blk %v", + blocksProcessed, time.Now().Sub(start), txsCached, + s.cfg.MaxCachedTxs-txsCached, txsCached/blocksProcessed) + + start = time.Now() + err = s.db.BlockTxUpdate(ctx, txs) + if err != nil { + return fmt.Errorf("block tx update: %w", err) + } + // leveldb does all kinds of allocations, force GC to lower + // memory preassure. + logMemStats() + runtime.GC() + + log.Infof("Flushing txs complete %v took %v", + txsCached, time.Now().Sub(start)) + + height += uint64(blocksProcessed) + + // Record height in metadata + var dbHeight [8]byte + binary.BigEndian.PutUint64(dbHeight[:], height) + err = s.db.MetadataPut(ctx, TxIndexHeightKey, dbHeight[:]) + if err != nil { + return fmt.Errorf("metadata tx height: %w", err) + } + + // If set we may have to exit early + if circuitBreaker { + log.Infof("Indexed transactions to height: %v", height-1) + if height >= maxHeight { + return nil + } + } + } +} + +// SyncIndexersToHeight tries to move the various indexers to the suplied +// height (inclusive). +func (s *Server) SyncIndexersToHeight(ctx context.Context, height uint64) error { + log.Tracef("SyncIndexersToHeight") + defer log.Tracef("SyncIndexersToHeight exit") + + // Outputs index + uhBE, err := s.db.MetadataGet(ctx, UtxoIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + return fmt.Errorf("utxo indexer metadata get: %w", err) + } + uhBE = make([]byte, 8) + } + heightUtxo := binary.BigEndian.Uint64(uhBE) + countUtxo := int64(height) - int64(heightUtxo) + if countUtxo >= 0 { + err := s.UtxoIndexer(ctx, heightUtxo, uint64(countUtxo+1)) + if err != nil { + return fmt.Errorf("utxo indexer: %w", err) + } + } + + // Transactions index + thBE, err := s.db.MetadataGet(ctx, TxIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + return fmt.Errorf("tx indexer metadata get: %w", err) + } + thBE = make([]byte, 8) + } + heightTx := binary.BigEndian.Uint64(thBE) + countTx := int64(height) - int64(heightTx) + if countTx >= 0 { + err := s.TxIndexer(ctx, heightTx, uint64(countTx+1)) + if err != nil { + return fmt.Errorf("tx indexer: %w", err) + } + } + + return nil +} diff --git a/service/tbc/crawler_test.go b/service/tbc/crawler_test.go new file mode 100644 index 000000000000..44e3d0357371 --- /dev/null +++ b/service/tbc/crawler_test.go @@ -0,0 +1,125 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "testing" + + "github.com/hemilabs/heminetwork/database/tbcd" +) + +//func TestIndex(t *testing.T) { +// t.Skip() +// logLevel := "INFO" +// loggo.ConfigureLoggers(logLevel) +// s, err := NewServer(&Config{ +// Network: "testnet3", +// }) +// if err != nil { +// t.Fatal(err) +// } +// +// ctx, cancel := context.WithCancel(context.Background()) +// defer cancel() +// +// // Open db. +// s.cfg.LevelDBHome = "~/.tbcd" +// s.db, err = level.New(ctx, filepath.Join(s.cfg.LevelDBHome, s.cfg.Network)) +// if err != nil { +// t.Fatal(err) +// } +// defer s.db.Close() +// +// start := time.Now() +// err = s.indexer(ctx) +// if err != nil { +// t.Fatal(err) +// } +// t.Logf("done at %v", time.Now().Sub(start)) +//} +// +//func TestUtxo(t *testing.T) { +// t.Skip() +// +// dc := &spew.ConfigState{ +// DisableMethods: true, +// } +// +// utxos := make(map[tbcd.Outpoint]tbcd.Utxo, 100) +// hash := sha256.Sum256([]byte("Hello, world!")) +// index := uint32(1) +// op := tbcd.NewOutpoint(hash, index) +// hash2 := sha256.Sum256([]byte("Hello, world!2")) +// op2 := tbcd.NewOutpoint(hash2, index) +// utxo := tbcd.Utxo{} +// utxos[op] = utxo +// utxos[op2] = utxo +// t.Logf("%v", dc.Sdump(utxos)) +// t.Logf("%v", len(op.String())) +// +// for k := range utxos { +// t.Logf("%T", k) +// } +// +// type myt [2]byte +// var m myt +// m[0] = 1 +// t.Logf("%T", m) +// t.Logf("%x", m) +// t.Logf("%v", len(m)) +// +// var mx myt +// mx[0] = 2 +// mm := make(map[myt]int) +// mm[m] = 1234 +// mm[mx] = 5678 +// t.Logf("%v", dc.Sdump(mm)) +// +// t.Logf("%v", spew.Sdump(utxos)) +//} + +// Test the various mapsizes +// run with go test -v -bench . -benchmem -run=BenchmarkMap +func allocateMap(size int) map[tbcd.Outpoint]tbcd.Utxo { + m := make(map[tbcd.Outpoint]tbcd.Utxo, size) + for i := 0; i < size; i++ { + m[tbcd.Outpoint{}] = tbcd.Utxo{} + } + return m +} + +func BenchmarkMap10(b *testing.B) { + for i := 0; i < b.N; i++ { + allocateMap(10) + } +} + +func BenchmarkMap100(b *testing.B) { + for i := 0; i < b.N; i++ { + allocateMap(100) + } +} + +func BenchmarkMap10000(b *testing.B) { + for i := 0; i < b.N; i++ { + allocateMap(10000) + } +} + +func BenchmarkMap100000(b *testing.B) { + for i := 0; i < b.N; i++ { + allocateMap(100000) + } +} + +// BenchmarkMap1000000 seems to indicate that 1 million utxos use about +// 182714418 bytes which is about 174MB on linux/arm64. +// Or, about 183 per cache entry. 100 bytes for the key and value (36+44) and +// 83 in overhead. +func BenchmarkMap1000000(b *testing.B) { + for i := 0; i < b.N; i++ { + allocateMap(1e6) + } +} diff --git a/service/tbc/peer.go b/service/tbc/peer.go new file mode 100644 index 000000000000..2648418a78e1 --- /dev/null +++ b/service/tbc/peer.go @@ -0,0 +1,202 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "context" + "fmt" + "math/rand" + "net" + "sync" + "time" + + "github.com/btcsuite/btcd/wire" +) + +// XXX wire could use some contexts, + +func writeTimeout(timeout time.Duration, conn net.Conn, msg wire.Message, pver uint32, btcnet wire.BitcoinNet) error { + conn.SetWriteDeadline(time.Now().Add(timeout)) + _, err := wire.WriteMessageWithEncodingN(conn, msg, pver, btcnet, + wire.LatestEncoding) + return err +} + +func readTimeout(timeout time.Duration, conn net.Conn, pver uint32, btcnet wire.BitcoinNet) (wire.Message, error) { + conn.SetReadDeadline(time.Now().Add(timeout)) + _, msg, _, err := wire.ReadMessageWithEncodingN(conn, pver, btcnet, + wire.LatestEncoding) + return msg, err +} + +type peer struct { + mtx sync.RWMutex + isDialing bool + conn net.Conn + connected time.Time + + address string + + protocolVersion uint32 + network wire.BitcoinNet + + remoteVersion *wire.MsgVersion + addrV2 bool +} + +func NewPeer(network wire.BitcoinNet, address string) (*peer, error) { + // XXX parse address and return failure if it's wrong + return &peer{ + protocolVersion: wire.ProtocolVersion, + network: network, + address: address, + }, nil +} + +func (p *peer) String() string { + return p.address +} + +func (p *peer) write(timeout time.Duration, msg wire.Message) error { + p.conn.SetWriteDeadline(time.Now().Add(timeout)) + _, err := wire.WriteMessageWithEncodingN(p.conn, msg, p.protocolVersion, + p.network, wire.LatestEncoding) + return err +} + +func (p *peer) read() (wire.Message, error) { + // XXX contexts would be nice + p.conn.SetReadDeadline(time.Time{}) // never timeout on reads + _, msg, _, err := wire.ReadMessageWithEncodingN(p.conn, p.protocolVersion, + p.network, wire.LatestEncoding) + return msg, err +} + +func (p *peer) handshake(ctx context.Context, conn net.Conn) error { + log.Tracef("handshake %v -> %v", conn.LocalAddr(), conn.RemoteAddr()) + defer log.Tracef("handshake exit %v -> %v", conn.LocalAddr(), conn.RemoteAddr()) + + // 1. send our version + // 2. receive version + // 3. send sendaddrv2 + // 4. send verack + // 5. receive sendaddrv2, verack or ignore + + defaultHandshakeTimeout := 5 * time.Second + us := &wire.NetAddress{Timestamp: time.Now()} + them := &wire.NetAddress{Timestamp: time.Now()} + msg := wire.NewMsgVersion(us, them, uint64(rand.Int63()), 0) + err := writeTimeout(defaultHandshakeTimeout, conn, msg, p.protocolVersion, p.network) + if err != nil { + return fmt.Errorf("could not write version message: %w", err) + } + + // 2. receive version + rmsg, err := readTimeout(defaultHandshakeTimeout, conn, p.protocolVersion, p.network) + if err != nil { + return fmt.Errorf("could not read version message: %w", err) + } + + v, ok := rmsg.(*wire.MsgVersion) + if !ok { + return fmt.Errorf("expected version message") + } + p.remoteVersion = v + + // 3. send sendaddrv2 + if v.ProtocolVersion >= 70016 { + err = writeTimeout(defaultHandshakeTimeout, conn, wire.NewMsgSendAddrV2(), p.protocolVersion, p.network) + if err != nil { + return fmt.Errorf("could not send sendaddrv2: %w", err) + } + } + + // 4. send verack + err = writeTimeout(defaultHandshakeTimeout, conn, wire.NewMsgVerAck(), p.protocolVersion, p.network) + if err != nil { + return fmt.Errorf("could not send verack: %w", err) + } + + for count := 0; count < 3; count++ { + msg, err := readTimeout(defaultHandshakeTimeout, conn, p.protocolVersion, p.network) + if err == wire.ErrUnknownMessage { + continue + } else if err != nil { + return fmt.Errorf("handshake read: %w", err) + } + + switch msg.(type) { + case *wire.MsgVerAck: + return nil + case *wire.MsgSendAddrV2: + p.addrV2 = true + continue + default: + return fmt.Errorf("unexpected message type: %T", msg) + } + } + + return fmt.Errorf("handshake failed") +} + +func (p *peer) connect(ctx context.Context) error { + log.Tracef("connect %v", p.address) // not locked but ok + defer log.Tracef("connect exit %v", p.address) + + p.mtx.Lock() + if p.isDialing { + p.mtx.Unlock() + return fmt.Errorf("already dialing %v", p.address) + } + if p.conn != nil { + p.mtx.Unlock() + return fmt.Errorf("already open %v", p.address) + } + p.isDialing = true + p.mtx.Unlock() + + d := net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 9 * time.Second, + } + + log.Debugf("dialing %s", p.address) + conn, err := d.DialContext(ctx, "tcp", p.address) + if err != nil { + return fmt.Errorf("dial %v: %w", p.address, err) + } + log.Debugf("done dialing %s", p.address) + + err = p.handshake(ctx, conn) + if err != nil { + return fmt.Errorf("handshake %v: %w", p.address, err) + } + + p.mtx.Lock() + p.conn = conn + p.isDialing = false + p.connected = time.Now() + p.mtx.Unlock() + + return nil +} + +func (p *peer) close() error { + log.Tracef("close") + defer log.Tracef("close exit") + + p.mtx.Lock() + defer p.mtx.Unlock() + if p.conn != nil { + return p.conn.Close() + } + return fmt.Errorf("already closed") +} + +func (p *peer) isConnected() bool { + p.mtx.Lock() + defer p.mtx.Unlock() + return !p.isDialing +} diff --git a/service/tbc/rpc.go b/service/tbc/rpc.go new file mode 100644 index 000000000000..1d593292c918 --- /dev/null +++ b/service/tbc/rpc.go @@ -0,0 +1,559 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "context" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "net/http" + "sync" + "time" + + "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" + "nhooyr.io/websocket" + + "github.com/hemilabs/heminetwork/api" + "github.com/hemilabs/heminetwork/api/protocol" + "github.com/hemilabs/heminetwork/api/tbcapi" + "github.com/hemilabs/heminetwork/database" + "github.com/hemilabs/heminetwork/database/tbcd/level" +) + +type tbcWs struct { + wg sync.WaitGroup + addr string + conn *protocol.WSConn + sessionID string + requestContext context.Context +} + +func (s *Server) handleWebsocketRead(ctx context.Context, ws *tbcWs) { + defer ws.wg.Done() + + log.Tracef("handleWebsocketRead: %v", ws.addr) + defer log.Tracef("handleWebsocketRead exit: %v", ws.addr) + + for { + cmd, id, payload, err := tbcapi.Read(ctx, ws.conn) + if err != nil { + var ce websocket.CloseError + if errors.As(err, &ce) { + log.Tracef("handleWebsocketRead: %v", err) + return + } + if errors.Is(err, io.EOF) { + log.Tracef("handleWebsocketRead: EOF") + return + } + + log.Errorf("handleWebsocketRead: %v", err) + return + } + + switch cmd { + case tbcapi.CmdPingRequest: + err = s.handlePingRequest(ctx, ws, payload, id) + case tbcapi.CmdBlockHeadersByHeightRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.BlockHeadersByHeightRequest) + return s.handleBlockHeadersByHeightRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdBlockHeadersByHeightRawRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.BlockHeadersByHeightRawRequest) + return s.handleBlockHeadersByHeightRawRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdBlockHeadersBestRawRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.BlockHeadersBestRawRequest) + return s.handleBlockHeadersBestRawRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdBlockHeadersBestRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.BlockHeadersBestRequest) + return s.handleBlockHeadersBestRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdBalanceByAddressRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.BalanceByAddressRequest) + return s.handleBalanceByAddressRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdUtxosByAddressRawRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.UtxosByAddressRawRequest) + return s.handleUtxosByAddressRawRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdUtxosByAddressRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.UtxosByAddressRequest) + return s.handleUtxosByAddressRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdTxByIdRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.TxByIdRequest) + return s.handleTxByIdRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + case tbcapi.CmdTxByIdRawRequest: + handler := func(ctx context.Context) (any, error) { + req := payload.(*tbcapi.TxByIdRawRequest) + return s.handleTxByIdRawRequest(ctx, req) + } + + go s.handleRequest(ctx, ws, id, cmd, handler) + default: + err = fmt.Errorf("unknown command: %v", cmd) + } + + // Command failed + if err != nil { + log.Errorf("handleWebsocketRead %s %s %s: %v", + ws.addr, cmd, id, err) + return + } + } +} + +func (s *Server) handleRequest(ctx context.Context, ws *tbcWs, id string, cmd protocol.Command, handler func(ctx context.Context) (any, error)) { + log.Tracef("handleRequest: %s: %s", ws.addr, cmd) + defer log.Tracef("handleRequest exit: %s: %s", ws.addr, cmd) + + ctx, cancel := context.WithTimeout(ctx, s.requestTimeout) + defer cancel() + + // TODO(joshuasing): add rate limiting? + + res, err := handler(ctx) + if err != nil { + log.Errorf("Failed to handle %s request for %s: %v", cmd, ws.addr, err) + } + + if res == nil { + return + } + + // XXX: spew.Sdump should only be called when the log level is enabled. + log.Debugf("Responding to %s request with %v", cmd, spew.Sdump(res)) + + if err = tbcapi.Write(ctx, ws.conn, id, res); err != nil { + log.Errorf("Failed to handle %s request for %s: protocol write failed: %v", + cmd, ws.addr, err) + } + + // Request processed successfully + s.cmdsProcessed.Inc() +} + +func (s *Server) handlePingRequest(ctx context.Context, ws *tbcWs, payload any, id string) error { + log.Tracef("handlePingRequest: %v", ws.addr) + defer log.Tracef("handlePingRequest exit: %v", ws.addr) + + p, ok := payload.(*tbcapi.PingRequest) + if !ok { + return fmt.Errorf("invalid payload type: %T", payload) + } + + res := &tbcapi.PingResponse{ + OriginTimestamp: p.Timestamp, + Timestamp: time.Now().Unix(), + } + + // XXX: spew.Sdump should only be called when the log level is enabled. + log.Tracef("responding with %v", spew.Sdump(res)) + + if err := tbcapi.Write(ctx, ws.conn, id, res); err != nil { + return fmt.Errorf("handlePingRequest write: %v %v", + ws.addr, err) + } + + // Ping request processed successfully + s.cmdsProcessed.Inc() + return nil +} + +func (s *Server) handleBlockHeadersByHeightRequest(ctx context.Context, req *tbcapi.BlockHeadersByHeightRequest) (any, error) { + log.Tracef("handleBtcBlockHeadersByHeightRequest") + defer log.Tracef("handleBtcBlockHeadersByHeightRequest exit") + + wireBlockHeaders, err := s.BlockHeadersByHeight(ctx, uint64(req.Height)) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + return &tbcapi.BlockHeadersByHeightResponse{ + Error: protocol.RequestErrorf("block headers not found at height %d", req.Height), + }, nil + } + + e := protocol.NewInternalError(err) + return &tbcapi.BlockHeadersByHeightResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.BlockHeadersByHeightResponse{ + BlockHeaders: wireBlockHeadersToTBC(wireBlockHeaders), + }, nil +} + +func (s *Server) handleBlockHeadersByHeightRawRequest(ctx context.Context, req *tbcapi.BlockHeadersByHeightRawRequest) (any, error) { + log.Tracef("handleBtcBlockHeadersByHeightRawRequest") + defer log.Tracef("handleBtcBlockHeadersByHeightRawRequest exit") + + rawBlockHeaders, err := s.RawBlockHeadersByHeight(ctx, uint64(req.Height)) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + return &tbcapi.BlockHeadersByHeightRawResponse{ + Error: protocol.RequestErrorf("block headers not found at height %d", req.Height), + }, nil + } + + e := protocol.NewInternalError(err) + return &tbcapi.BlockHeadersByHeightRawResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.BlockHeadersByHeightRawResponse{ + BlockHeaders: rawBlockHeaders, + }, nil +} + +func (s *Server) handleBlockHeadersBestRawRequest(ctx context.Context, _ *tbcapi.BlockHeadersBestRawRequest) (any, error) { + log.Tracef("handleBlockHeadersBestRawRequest") + defer log.Tracef("handleBlockHeadersBestRawRequest exit") + + height, blockHeaders, err := s.RawBlockHeadersBest(ctx) + if err != nil { + e := protocol.NewInternalError(err) + return &tbcapi.BlockHeadersBestRawResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.BlockHeadersBestRawResponse{ + Height: height, + BlockHeaders: blockHeaders, + }, nil +} + +func (s *Server) handleBlockHeadersBestRequest(ctx context.Context, _ *tbcapi.BlockHeadersBestRequest) (any, error) { + log.Tracef("handleBlockHeadersBestRequest") + defer log.Tracef("handleBlockHeadersBestRequest exit") + + height, blockHeaders, err := s.BlockHeadersBest(ctx) + if err != nil { + e := protocol.NewInternalError(err) + return &tbcapi.BlockHeadersBestResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.BlockHeadersBestResponse{ + Height: height, + BlockHeaders: wireBlockHeadersToTBC(blockHeaders), + }, nil +} + +func (s *Server) handleBalanceByAddressRequest(ctx context.Context, req *tbcapi.BalanceByAddressRequest) (any, error) { + log.Tracef("handleBalanceByAddressRequest") + defer log.Tracef("handleBalanceByAddressRequest exit") + + balance, err := s.BalanceByAddress(ctx, req.Address) + if err != nil { + e := protocol.NewInternalError(err) + return &tbcapi.BalanceByAddressResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.BalanceByAddressResponse{ + Balance: balance, + }, nil +} + +func (s *Server) handleUtxosByAddressRawRequest(ctx context.Context, req *tbcapi.UtxosByAddressRawRequest) (any, error) { + log.Tracef("handleUtxosByAddressRawRequest") + defer log.Tracef("handleUtxosByAddressRawRequest exit") + + utxos, err := s.UtxosByAddress(ctx, req.Address, uint64(req.Start), uint64(req.Count)) + if err != nil { + if errors.Is(err, level.ErrIterator) { + e := protocol.NewInternalError(err) + return &tbcapi.UtxosByAddressRawResponse{ + Error: e.ProtocolError(), + }, err + } + + return &tbcapi.UtxosByAddressRawResponse{ + Error: protocol.RequestErrorf("error getting utxos for address: %s", req.Address), + }, nil + } + + var responseUtxos []api.ByteSlice + for _, utxo := range utxos { + responseUtxos = append(responseUtxos, utxo[:]) + } + + return &tbcapi.UtxosByAddressRawResponse{ + Utxos: responseUtxos, + }, nil +} + +func (s *Server) handleUtxosByAddressRequest(ctx context.Context, req *tbcapi.UtxosByAddressRequest) (any, error) { + log.Tracef("handleUtxosByAddressRequest") + defer log.Tracef("handleUtxosByAddressRequest exit") + + utxos, err := s.UtxosByAddress(ctx, req.Address, uint64(req.Start), uint64(req.Count)) + if err != nil { + if errors.Is(err, level.ErrIterator) { + e := protocol.NewInternalError(err) + return &tbcapi.UtxosByAddressResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.UtxosByAddressResponse{ + Error: protocol.RequestErrorf("error getting utxos for address: %s", req.Address), + }, nil + } + + var responseUtxos []tbcapi.Utxo + for _, utxo := range utxos { + responseUtxos = append(responseUtxos, tbcapi.Utxo{ + TxId: api.ByteSlice(utxo.ScriptHashSlice()), + Value: utxo.Value(), + OutIndex: utxo.OutputIndex(), + }) + } + + return &tbcapi.UtxosByAddressResponse{ + Utxos: responseUtxos, + }, nil +} + +func (s *Server) handleTxByIdRawRequest(ctx context.Context, req *tbcapi.TxByIdRawRequest) (any, error) { + log.Tracef("handleTxByIdRawRequest") + defer log.Tracef("handleTxByIdRawRequest exit") + + if len(req.TxId) != 32 { + responseErr := protocol.RequestErrorf("invalid tx id") + return &tbcapi.TxByIdRawResponse{ + Error: responseErr, + }, nil + } + + tx, err := s.TxById(ctx, [32]byte(req.TxId)) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + responseErr := protocol.RequestErrorf("tx not found: %s", hex.EncodeToString(req.TxId)) + return &tbcapi.TxByIdRawResponse{ + Error: responseErr, + }, nil + } + + responseErr := protocol.NewInternalError(err) + return &tbcapi.TxByIdRawResponse{ + Error: responseErr.ProtocolError(), + }, responseErr + } + + b, err := tx2Bytes(tx) + if err != nil { + e := protocol.NewInternalError(err) + return &tbcapi.TxByIdRawResponse{ + Error: e.ProtocolError(), + }, e + } + + return &tbcapi.TxByIdRawResponse{ + Tx: b, + }, nil +} + +func (s *Server) handleTxByIdRequest(ctx context.Context, req *tbcapi.TxByIdRequest) (any, error) { + log.Tracef("handleTxByIdRequest") + defer log.Tracef("handleTxByIdRequest exit") + + if len(req.TxId) != 32 { + responseErr := protocol.RequestErrorf("invalid tx id") + return &tbcapi.TxByIdResponse{ + Error: responseErr, + }, nil + } + + tx, err := s.TxById(ctx, [32]byte(req.TxId)) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + responseErr := protocol.RequestErrorf("not found: %s", hex.EncodeToString(req.TxId)) + return &tbcapi.TxByIdResponse{ + Error: responseErr, + }, nil + } + + responseErr := protocol.NewInternalError(err) + return &tbcapi.TxByIdResponse{ + Error: responseErr.ProtocolError(), + }, responseErr + } + + return &tbcapi.TxByIdResponse{ + Tx: *wireTxToTbcapiTx(tx), + }, nil +} + +func (s *Server) handleWebsocket(w http.ResponseWriter, r *http.Request) { + log.Tracef("handleWebsocket: %v", r.RemoteAddr) + defer log.Tracef("handleWebsocket exit: %v", r.RemoteAddr) + + conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{ + CompressionMode: websocket.CompressionContextTakeover, + }) + if err != nil { + log.Errorf("Failed to accept websocket connection for %s: %v", + r.RemoteAddr, err) + return + } + defer conn.Close(websocket.StatusNormalClosure, "") // Force close connection + + ws := &tbcWs{ + addr: r.RemoteAddr, + conn: protocol.NewWSConn(conn), + requestContext: r.Context(), + } + + if ws.sessionID, err = s.newSession(ws); err != nil { + log.Errorf("An error occurred while creating session: %v", err) + return + } + defer s.deleteSession(ws.sessionID) + + ws.wg.Add(1) + go s.handleWebsocketRead(r.Context(), ws) + + // Always ping, required by protocol. + ping := &tbcapi.PingRequest{ + Timestamp: time.Now().Unix(), + } + + log.Tracef("Responding with %v", spew.Sdump(ping)) + if err = tbcapi.Write(r.Context(), ws.conn, "0", ping); err != nil { + log.Errorf("Write ping: %v", err) + } + + log.Infof("Connection from %v", r.RemoteAddr) + + // Wait for termination + ws.wg.Wait() + + log.Infof("Connection terminated from %v", r.RemoteAddr) +} + +func (s *Server) newSession(ws *tbcWs) (string, error) { + for { + // Create random hexadecimal string to use as an ID + id, err := randHexId(16) + if err != nil { + return "", fmt.Errorf("generate session id: %w", err) + } + + // Ensure the key is not already in use, if it is then try again. + s.mtx.Lock() + if _, ok := s.sessions[id]; ok { + s.mtx.Unlock() + continue + } + s.sessions[id] = ws + s.mtx.Unlock() + + return id, nil + } +} + +func (s *Server) deleteSession(id string) { + s.mtx.Lock() + _, ok := s.sessions[id] + delete(s.sessions, id) + s.mtx.Unlock() + + if !ok { + log.Errorf("id not found in sessions %s", id) + } +} + +func randHexId(length int) (string, error) { + b := make([]byte, length) + if _, err := rand.Read(b); err != nil { + return "", fmt.Errorf("read random bytes: %w", err) + } + return hex.EncodeToString(b), nil +} + +func wireBlockHeadersToTBC(w []*wire.BlockHeader) []*tbcapi.BlockHeader { + blockHeaders := make([]*tbcapi.BlockHeader, len(w)) + for i, bh := range w { + blockHeaders[i] = &tbcapi.BlockHeader{ + Version: bh.Version, + PrevHash: bh.PrevBlock.String(), + MerkleRoot: bh.MerkleRoot.String(), + Timestamp: bh.Timestamp.Unix(), + Bits: fmt.Sprintf("%x", bh.Bits), + Nonce: bh.Nonce, + } + } + return blockHeaders +} + +func wireTxToTbcapiTx(w *wire.MsgTx) *tbcapi.Tx { + a := &tbcapi.Tx{ + Version: w.Version, + LockTime: w.LockTime, + TxIn: []*tbcapi.TxIn{}, + TxOut: []*tbcapi.TxOut{}, + } + + for _, v := range w.TxIn { + a.TxIn = append(a.TxIn, &tbcapi.TxIn{ + Sequence: v.Sequence, + SignatureScript: api.ByteSlice(v.SignatureScript), + PreviousOutPoint: tbcapi.OutPoint{ + Hash: api.ByteSlice(v.PreviousOutPoint.Hash[:]), + Index: v.PreviousOutPoint.Index, + }, + }) + + for _, b := range v.Witness { + a.TxIn[len(a.TxIn)-1].Witness = append(a.TxIn[len(a.TxIn)-1].Witness, + api.ByteSlice(b)) + } + } + + for _, v := range w.TxOut { + a.TxOut = append(a.TxOut, &tbcapi.TxOut{ + Value: v.Value, + PkScript: api.ByteSlice(v.PkScript), + }) + } + + return a +} diff --git a/service/tbc/tbc.go b/service/tbc/tbc.go new file mode 100644 index 000000000000..a9ead495b417 --- /dev/null +++ b/service/tbc/tbc.go @@ -0,0 +1,1777 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "math/rand" + "net" + "net/http" + "path/filepath" + "slices" + "strconv" + "sync" + "time" + + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" + "github.com/dustin/go-humanize" + "github.com/juju/loggo" + "github.com/prometheus/client_golang/prometheus" + "github.com/syndtr/goleveldb/leveldb" + + "github.com/hemilabs/heminetwork/api" + "github.com/hemilabs/heminetwork/api/tbcapi" + "github.com/hemilabs/heminetwork/database" + "github.com/hemilabs/heminetwork/database/tbcd" + "github.com/hemilabs/heminetwork/database/tbcd/level" + "github.com/hemilabs/heminetwork/service/deucalion" +) + +const ( + logLevel = "INFO" + + promSubsystem = "tbc_service" // Prometheus + + mainnetPort = "8333" + testnetPort = "18333" + localnetPort = "18444" + + defaultPeersWanted = 64 + defaultPendingBlocks = 128 // 128 * ~4MB max memory use + + defaultMaxCachedTxs = 1e6 // dual purpose cache, max key 69, max value 36 + + networkLocalnet = "localnet" // XXX this needs to be rethought + + defaultCmdTimeout = 4 * time.Second +) + +var ( + testnetSeeds = []string{ + "testnet-seed.bitcoin.jonasschnelli.ch", + "seed.tbtc.petertodd.org", + "seed.testnet.bitcoin.sprovoost.nl", + "testnet-seed.bluematt.me", + } + mainnetSeeds = []string{ + "seed.bitcoin.sipa.be", + "dnsseed.bluematt.me", + "dnsseed.bitcoin.dashjr.org", + "seed.bitcoinstats.com", + "seed.bitnodes.io", + "seed.bitcoin.jonasschnelli.ch", + } +) + +var log = loggo.GetLogger("tbc") + +func init() { + loggo.ConfigureLoggers(logLevel) + rand.Seed(time.Now().UnixNano()) // used for seeding, ok to be math.rand +} + +func tx2Bytes(tx *wire.MsgTx) ([]byte, error) { + var b bytes.Buffer + if err := tx.Serialize(&b); err != nil { + return nil, err + } + + return b.Bytes(), nil +} + +func bytes2Tx(b []byte) (*wire.MsgTx, error) { + var w wire.MsgTx + if err := w.Deserialize(bytes.NewReader(b)); err != nil { + return nil, err + } + + return &w, nil +} + +func header2Bytes(wbh *wire.BlockHeader) ([]byte, error) { + var b bytes.Buffer + err := wbh.Serialize(&b) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +func h2b(wbh *wire.BlockHeader) []byte { + hb, err := header2Bytes(wbh) + if err != nil { + panic(err) + } + return hb +} + +func bytes2Header(header []byte) (*wire.BlockHeader, error) { + var bh wire.BlockHeader + err := bh.Deserialize(bytes.NewReader(header)) + if err != nil { + return nil, fmt.Errorf("Deserialize: %v", err) + } + return &bh, nil +} + +func headerTime(header []byte) *time.Time { + h, err := bytes2Header(header) + if err != nil { + return nil + } + return &h.Timestamp +} + +func hashEqual(h1 chainhash.Hash, h2 chainhash.Hash) bool { + // Fuck you chainhash package + return h1.IsEqual(&h2) +} + +func sliceChainHash(ch chainhash.Hash) []byte { + // Fuck you chainhash package + return ch[:] +} + +type blockPeer struct { + expire time.Time // when does this command expire + peer string // who was handling it +} + +type Config struct { + AutoIndex bool + BlockSanity bool + RegtestPort string + LevelDBHome string + ListenAddress string + LogLevel string + MaxCachedTxs int + Network string + PrometheusListenAddress string +} + +func NewDefaultConfig() *Config { + return &Config{ + ListenAddress: tbcapi.DefaultListen, + LogLevel: logLevel, + MaxCachedTxs: defaultMaxCachedTxs, + } +} + +type Server struct { + mtx sync.RWMutex + wg sync.WaitGroup + + cfg *Config + + // stats + printTime time.Time + blocksSize uint64 // cumulative block size written + blocksInserted map[string]struct{} + blocksDuplicate int + + // bitcoin network + wireNet wire.BitcoinNet + chainParams *chaincfg.Params + timeSource blockchain.MedianTimeSource + port string + seeds []string + + peers map[string]*peer // active but not necessarily connected + blocks map[string]*blockPeer // outstanding block downloads [hash]when/where + + // IBD hints + lastBlockHeader tbcd.BlockHeader + + // reentrancy flags for the indexers + utxoIndexerRunning bool + txIndexerRunning bool + + db tbcd.Database + + // Prometheus + isRunning bool + cmdsProcessed prometheus.Counter + + // WebSockets + sessions map[string]*tbcWs + requestTimeout time.Duration + + // ignoreUlimit will explicitly not check ulimit settings on the host + // machine, this is useful for very small datasets/chains + ignoreUlimit bool +} + +func NewServer(cfg *Config) (*Server, error) { + if cfg == nil { + cfg = NewDefaultConfig() + } + defaultRequestTimeout := 10 * time.Second // XXX: make config option? + s := &Server{ + cfg: cfg, + printTime: time.Now().Add(10 * time.Second), + blocks: make(map[string]*blockPeer, defaultPendingBlocks), + peers: make(map[string]*peer, defaultPeersWanted), + blocksInserted: make(map[string]struct{}, 8192), // stats + timeSource: blockchain.NewMedianTime(), + cmdsProcessed: prometheus.NewCounter(prometheus.CounterOpts{ + Subsystem: promSubsystem, + Name: "rpc_calls_total", + Help: "The total number of successful RPC commands", + }), + sessions: make(map[string]*tbcWs), + requestTimeout: defaultRequestTimeout, + } + + // We could use a PGURI verification here. + + switch cfg.Network { + case "mainnet": + s.port = mainnetPort + s.wireNet = wire.MainNet + s.chainParams = &chaincfg.MainNetParams + s.seeds = mainnetSeeds + case "testnet3": + s.port = testnetPort + s.wireNet = wire.TestNet3 + s.chainParams = &chaincfg.TestNet3Params + s.seeds = testnetSeeds + case networkLocalnet: + s.port = localnetPort + s.wireNet = wire.TestNet + s.chainParams = &chaincfg.RegressionNetParams + default: + return nil, fmt.Errorf("invalid network: %v", cfg.Network) + } + + return s, nil +} + +// DB exports the underlying database. This should only be used in tests. +func (s *Server) DB() tbcd.Database { + return s.db +} + +// blockPeerExpire removes expired block downloads from the cache and returns +// the number of used cache slots. Lock must be held. +func (s *Server) blockPeerExpire() int { + log.Tracef("blockPeerExpire exit") + defer log.Tracef("blockPeerExpire exit") + + now := time.Now() + for k, v := range s.blocks { + if v == nil { + // not assigned a peer yet + continue + } + if !now.After(v.expire) { + continue + } + + // mark block as unassigned but do not give up cache slot + s.blocks[k] = nil + log.Infof("expired block: %v", k) // XXX maybe remove but add to stats + + // kill peer as well since it is slow + if p := s.peers[v.peer]; p != nil && p.conn != nil { + p.conn.Close() // this will tear down peer + } + } + return len(s.blocks) +} + +func (s *Server) getHeaders(ctx context.Context, p *peer, lastHeaderHash []byte) error { + bh, err := bytes2Header(lastHeaderHash) + if err != nil { + return fmt.Errorf("invalid header: %v", err) + } + hash := bh.BlockHash() + ghs := wire.NewMsgGetHeaders() + ghs.AddBlockLocatorHash(&hash) + err = p.write(defaultCmdTimeout, ghs) + if err != nil { + return fmt.Errorf("write get headers: %v", err) + } + + return nil +} + +func (s *Server) seed(pctx context.Context, peersWanted int) ([]tbcd.Peer, error) { + log.Tracef("seed") + defer log.Tracef("seed exit") + + peers, err := s.db.PeersRandom(pctx, peersWanted) + if err != nil { + return nil, fmt.Errorf("peers random: %v", err) + } + // return peers from db first + if len(peers) >= peersWanted { + return peers, nil + } + + // Seed + resolver := &net.Resolver{} + ctx, cancel := context.WithTimeout(pctx, 15*time.Second) + defer cancel() + + errorsSeen := 0 + var addrs []net.IP + for k := range s.seeds { + ips, err := resolver.LookupIP(ctx, "ip", s.seeds[k]) + if err != nil { + log.Errorf("lookup: %v", err) + errorsSeen++ + continue + } + addrs = append(addrs, ips...) + } + if errorsSeen == len(s.seeds) { + return nil, fmt.Errorf("could not seed") + } + + // insert into peers table + for k := range addrs { + peers = append(peers, tbcd.Peer{ + Host: addrs[k].String(), + Port: s.port, + }) + } + + // return fake peers but don't save them to the database + return peers, nil +} + +func (s *Server) seedForever(ctx context.Context, peersWanted int) ([]tbcd.Peer, error) { + log.Tracef("seedForever") + defer log.Tracef("seedForever") + + minW := 5 + maxW := 59 + for { + holdOff := time.Duration(minW+rand.Intn(maxW-minW)) * time.Second + var em string + peers, err := s.seed(ctx, peersWanted) + if err != nil { + em = fmt.Sprintf("seed error: %v, retrying in %v", err, holdOff) + } else if peers != nil && len(peers) == 0 { + em = fmt.Sprintf("no peers found, retrying in %v", holdOff) + } else { + // great success! + return peers, nil + } + log.Errorf("%v", em) + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(holdOff): + } + } +} + +func (s *Server) peerAdd(p *peer) { + log.Tracef("peerAdd: %v", p.address) + s.mtx.Lock() + s.peers[p.address] = p + s.mtx.Unlock() +} + +func (s *Server) peerDelete(address string) { + log.Tracef("peerDelete: %v", address) + s.mtx.Lock() + delete(s.peers, address) + s.mtx.Unlock() +} + +func (s *Server) peersLen() int { + s.mtx.Lock() + defer s.mtx.Unlock() + return len(s.peers) +} + +func (s *Server) peerManager(ctx context.Context) error { + log.Tracef("peerManager") + defer log.Tracef("peerManager exit") + + // Channel for peering signals + peersWanted := defaultPeersWanted + peerC := make(chan string, peersWanted) + + log.Infof("Peer manager connecting to %v peers", peersWanted) + seeds, err := s.seedForever(ctx, peersWanted) + if err != nil { + // context canceled + return fmt.Errorf("seed: %w", err) + } + if len(seeds) == 0 { + // should not happen + return fmt.Errorf("no seeds found") + } + + // Add a ticker that times out every 27 seconds regardless of what is + // going on. This will be nice and jittery and detect bad beers + // peridiocally. + loopTimeout := 27 * time.Second + loopTicker := time.NewTicker(loopTimeout) + + x := 0 + for { + peersActive := s.peersLen() + log.Debugf("peerManager active %v wanted %v", peersActive, peersWanted) + if peersActive < peersWanted { + // XXX we may want to make peers play along with waitgroup + + // Connect peer + for i := 0; i < peersWanted-peersActive; i++ { + address := net.JoinHostPort(seeds[x].Host, seeds[x].Port) + peer, err := NewPeer(s.wireNet, address) + if err != nil { + // This really should not happen + log.Errorf("new peer: %v", err) + continue + } + s.peerAdd(peer) + + go s.peerConnect(ctx, peerC, peer) + + x++ + if x >= len(seeds) { + // XXX duplicate code from above + seeds, err = s.seedForever(ctx, peersWanted) + if err != nil { + // Context canceled + return fmt.Errorf("seed: %w", err) + } + if len(seeds) == 0 { + // should not happen + return fmt.Errorf("no seeds found") + } + x = 0 + } + } + } + + // Unfortunately we need a timer here to restart the loop. The + // error is a laptop goes to sleep, all peers disconnect, RSTs + // are not seen by sleeping laptop, laptop wakes up. Now the + // expiration timers are all expired but not noticed by the + // laptop. + select { + case <-ctx.Done(): + return ctx.Err() + case address := <-peerC: + // peer exited, connect to new one + s.peerDelete(address) + log.Debugf("peer exited: %v", address) + case <-loopTicker.C: + log.Debugf("pinging active peers: %v", s.peersLen()) + go s.pingAllPeers(ctx) + loopTicker.Reset(loopTimeout) + } + } +} + +func (s *Server) localPeerManager(ctx context.Context) error { + log.Tracef("localPeerManager") + defer log.Tracef("localPeerManager exit") + + peersWanted := 1 + peerC := make(chan string, peersWanted) + address := net.JoinHostPort("127.0.0.1", s.port) + peer, err := NewPeer(s.wireNet, address) + if err != nil { + return fmt.Errorf("new peer: %w", err) + } + + log.Infof("Local peer manager connecting to %v peers", peersWanted) + + for { + s.peerAdd(peer) + go s.peerConnect(ctx, peerC, peer) + + select { + case <-ctx.Done(): + return ctx.Err() + case address := <-peerC: + s.peerDelete(address) + log.Infof("peer exited: %v", address) + } + + // hold off on reconnect + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(10 * time.Second): + log.Infof("peer exited: %v", "hold of timeout") + } + } +} + +func (s *Server) startPeerManager(ctx context.Context) error { + log.Tracef("startPeerManager") + defer log.Tracef("startPeerManager exit") + + switch s.cfg.Network { + case networkLocalnet: + return s.localPeerManager(ctx) + } + return s.peerManager(ctx) +} + +func (s *Server) pingAllPeers(ctx context.Context) { + log.Tracef("pingAllPeers") + defer log.Tracef("pingAllPeers exit") + + // XXX reason and explain why this cannot be reentrant + s.mtx.Lock() + defer s.mtx.Unlock() + + for _, p := range s.peers { + select { + case <-ctx.Done(): + return + default: + } + if p.conn == nil { + continue + } + + // We don't really care about the response. We just want to + // write to the connection to make it fail if the other side + // went away. + log.Debugf("Pinging: %v", p) + err := p.write(defaultCmdTimeout, wire.NewMsgPing(uint64(time.Now().Unix()))) + if err != nil { + log.Errorf("ping %v: %v", p, err) + } + } +} + +func (s *Server) peerConnect(ctx context.Context, peerC chan string, p *peer) { + log.Tracef("peerConnect %v", p) + defer func() { + select { + case peerC <- p.String(): + default: + log.Tracef("could not signal peer channel: %v", p) + } + log.Tracef("peerConnect exit %v", p) + }() + + tctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + err := p.connect(tctx) + if err != nil { + go func(pp *peer) { + // Remove from database; it's ok to be aggressive if it + // failed with no route to host or failed with i/o + // timeout or invalid network (ipv4/ipv6). + // + // This does have the side-effect of draining the peer + // table during network outages but that is ok. The + // peers table will be rebuild based on DNS seeds. + host, port, err := net.SplitHostPort(pp.String()) + if err != nil { + log.Errorf("split host port: %v", err) + return + } + err = s.db.PeerDelete(ctx, host, port) + if err != nil { + log.Errorf("peer delete (%v): %v", pp, err) + } else { + log.Debugf("Peer delete: %v", pp) + } + }(p) + log.Debugf("connect: %v", err) + return + } + defer func() { + err := p.close() + if err != nil { + log.Errorf("peer disconnect: %v %v", p, err) + } + }() + + _ = p.write(defaultCmdTimeout, wire.NewMsgSendHeaders()) // Ask peer to send headers + _ = p.write(defaultCmdTimeout, wire.NewMsgGetAddr()) // Try to get network information + + log.Debugf("Peer connected: %v", p) + + // Pretend we are always in IBD. + // + // This obviously will put a pressure on the internet connection and + // database because each and every peer is racing at start of day. As + // multiple answers come in the insert of the headers fails or + // succeeds. If it fails no more headers will be requested from that + // peer. + bhs, err := s.db.BlockHeadersBest(ctx) + if err != nil { + log.Errorf("block headers best: %v", err) + // database is closed, nothing we can do, return here to avoid below + // panic + if errors.Is(err, leveldb.ErrClosed) { + return + } + } + if len(bhs) != 1 { + // XXX fix multiple tips + panic(len(bhs)) + } + log.Debugf("block header best hash: %s", bhs[0].Hash) + + err = s.getHeaders(ctx, p, bhs[0].Header) + if err != nil { + // This should not happen + log.Errorf("get headers: %v", err) + return + } + + // XXX kickstart block download, should happen in getHeaders + + verbose := false + for { + // See if we were interrupted, for the love of pete add ctx to wire + select { + case <-ctx.Done(): + return + default: + } + + msg, err := p.read() + if err == wire.ErrUnknownMessage { + // skip unknown + continue + } else if err != nil { + log.Debugf("peer read %v: %v", p, err) + return + } + + if verbose { + spew.Dump(msg) + } + + // XXX send wire message to pool reader + switch m := msg.(type) { + case *wire.MsgAddr: + go s.handleAddr(ctx, p, m) + + case *wire.MsgAddrV2: + go s.handleAddrV2(ctx, p, m) + + case *wire.MsgBlock: + go s.handleBlock(ctx, p, m) + + case *wire.MsgFeeFilter: + // XXX shut up + + case *wire.MsgInv: + go s.handleInv(ctx, p, m) + + case *wire.MsgHeaders: + go s.handleHeaders(ctx, p, m) + + case *wire.MsgPing: + go s.handlePing(ctx, p, m) + default: + log.Tracef("unhandled message type %v: %T\n", p, msg) + } + } +} + +func (s *Server) running() bool { + s.mtx.RLock() + defer s.mtx.RUnlock() + return s.isRunning +} + +func (s *Server) testAndSetRunning(b bool) bool { + s.mtx.Lock() + defer s.mtx.Unlock() + old := s.isRunning + s.isRunning = b + return old != s.isRunning +} + +func (s *Server) promRunning() float64 { + r := s.running() + if r { + return 1 + } + return 0 +} + +// blksMissing checks the block cache and the database and returns true if all +// blocks have not been downloaded. This function must be called with the lock +// held. +func (s *Server) blksMissing(ctx context.Context) bool { + // Do cheap memory check first + if len(s.blocks) != 0 { + return true + } + + // Do expensive database check + bm, err := s.db.BlocksMissing(ctx, 1) + if err != nil { + log.Errorf("blocks missing: %v", err) + return true // this is really kind of terminal + } + return len(bm) > 0 +} + +// blocksMissing checks the block cache and the database and returns true if all +// blocks have not been downloaded. +func (s *Server) blocksMissing(ctx context.Context) bool { + s.mtx.Lock() + defer s.mtx.Unlock() + + return s.blksMissing(ctx) +} + +func (s *Server) handleAddr(ctx context.Context, p *peer, msg *wire.MsgAddr) { + log.Tracef("handleAddr (%v): %v", p, len(msg.AddrList)) + defer log.Tracef("handleAddr exit (%v)", p) + + peers := make([]tbcd.Peer, 0, len(msg.AddrList)) + for k := range msg.AddrList { + peers = append(peers, tbcd.Peer{ + Host: msg.AddrList[k].IP.String(), + Port: strconv.Itoa(int(msg.AddrList[k].Port)), + }) + } + err := s.db.PeersInsert(ctx, peers) + // Don't log insert 0, its a dup. + if err != nil && !database.ErrZeroRows.Is(err) { + log.Errorf("%v", err) + } +} + +func (s *Server) handleAddrV2(ctx context.Context, p *peer, msg *wire.MsgAddrV2) { + log.Tracef("handleAddrV2 (%v): %v", p, len(msg.AddrList)) + defer log.Tracef("handleAddrV2 exit (%v)", p) + + peers := make([]tbcd.Peer, 0, len(msg.AddrList)) + for k := range msg.AddrList { + peers = append(peers, tbcd.Peer{ + Host: msg.AddrList[k].Addr.String(), + Port: strconv.Itoa(int(msg.AddrList[k].Port)), + }) + } + err := s.db.PeersInsert(ctx, peers) + // Don't log insert 0, its a dup. + if err != nil && !database.ErrZeroRows.Is(err) { + log.Errorf("%v", err) + } +} + +func (s *Server) handlePing(ctx context.Context, p *peer, msg *wire.MsgPing) { + log.Tracef("handlePing %v", p.address) + defer log.Tracef("handlePing exit %v", p.address) + + pong := wire.NewMsgPong(msg.Nonce) + err := p.write(defaultCmdTimeout, pong) + if err != nil { + log.Errorf("could not write pong message %v: %v", p.address, err) + return + } + log.Tracef("handlePing %v: pong %v", p.address, pong.Nonce) +} + +func (s *Server) handleInv(ctx context.Context, p *peer, msg *wire.MsgInv) { + log.Tracef("handleInv (%v)", p) + defer log.Tracef("handleInv exit (%v)", p) + + var bis []tbcd.BlockIdentifier + for k := range msg.InvList { + switch msg.InvList[k].Type { + case wire.InvTypeBlock: + + // XXX height is missing here, looks right but assert + // that this isn't broken. + log.Infof("handleInv: block %v", msg.InvList[k].Hash) + + bis = append(bis, tbcd.BlockIdentifier{ + Hash: msg.InvList[k].Hash[:], // fake out + }) + log.Infof("handleInv: block %v", msg.InvList[k].Hash) + case wire.InvTypeTx: + // XXX silence mempool for now + return + default: + log.Infof("handleInv: skipping inv type %v", msg.InvList[k].Type) + return + } + } + + // XXX This happens during block header download, we should not react + // Probably move into the invtype switch + log.Infof("download blocks if we like them") + // if len(bis) > 0 { + // s.mtx.Lock() + // defer s.mtx.Unlock() + // err := s.downloadBlocks(ctx, bis) + // if err != nil { + // log.Errorf("download blocks: %v", err) + // return + // } + // } +} + +func (s *Server) txIndexer(ctx context.Context) { + log.Tracef("txIndexer") + defer log.Tracef("txIndexer exit") + + if !s.cfg.AutoIndex { + return + } + + // only one txIndexer may run at any given time + s.mtx.Lock() + if s.txIndexerRunning { + s.mtx.Unlock() + return + } + s.txIndexerRunning = true + s.mtx.Unlock() + + // mark txIndexer not running on exit + defer func() { + s.mtx.Lock() + s.txIndexerRunning = false + s.mtx.Unlock() + }() + + if s.blocksMissing(ctx) { + return + } + + // Get height from db + he, err := s.db.MetadataGet(ctx, TxIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + log.Errorf("tx indexer metadata get: %v", err) + return + } + he = make([]byte, 8) + } + h := binary.BigEndian.Uint64(he) + + // Skip txIndexer if we are at best block height. This is a bit racy. + bhs, err := s.db.BlockHeadersBest(ctx) + if err != nil { + log.Errorf("utxo indexer block headers best: %v", err) + return + } + if len(bhs) != 1 { + log.Errorf("utxo indexer block headers best: unsuported fork") + return + } + + if bhs[0].Height != h-1 { + err = s.TxIndexer(ctx, h, 0) + if err != nil { + log.Errorf("tx indexer: %v", err) + return + } + } +} + +func (s *Server) utxoIndexer(ctx context.Context) { + log.Tracef("utxoIndexer") + defer log.Tracef("utxoIndexer exit") + + if !s.cfg.AutoIndex { + return + } + + // only one utxoIndexer may run at any given time + s.mtx.Lock() + if s.utxoIndexerRunning { + s.mtx.Unlock() + return + } + s.utxoIndexerRunning = true + s.mtx.Unlock() + + // mark utxoIndexer not running on exit + defer func() { + s.mtx.Lock() + s.utxoIndexerRunning = false + s.mtx.Unlock() + }() + + // exit if we aren't synced + if s.blocksMissing(ctx) { + return + } + + // Index all utxos + + // Get height from db + he, err := s.db.MetadataGet(ctx, UtxoIndexHeightKey) + if err != nil { + if !errors.Is(err, database.ErrNotFound) { + log.Errorf("utxo indexer metadata get: %v", err) + return + } + he = make([]byte, 8) + } + h := binary.BigEndian.Uint64(he) + + // Skip UtxoIndex if we are at best block height. This is a bit racy. + bhs, err := s.db.BlockHeadersBest(ctx) + if err != nil { + log.Errorf("utxo indexer block headers best: %v", err) + return + } + if len(bhs) != 1 { + log.Errorf("utxo indexer block headers best: unsuported fork") + return + } + + if bhs[0].Height != h-1 { + err = s.UtxoIndexer(ctx, h, 0) + if err != nil { + log.Errorf("utxo indexer: %v", err) + return + } + } + + // When utxo sync completes kick off tx sync + go s.txIndexer(ctx) +} + +func (s *Server) downloadBlock(ctx context.Context, p *peer, ch *chainhash.Hash) { + log.Tracef("downloadBlock") + defer log.Tracef("downloadBlock exit") + + getData := wire.NewMsgGetData() + getData.InvList = append(getData.InvList, + &wire.InvVect{ + Type: wire.InvTypeBlock, + Hash: *ch, + }) + + s.mtx.Lock() + defer s.mtx.Unlock() + err := p.write(defaultCmdTimeout, getData) + if err != nil { + // peer dead, make sure it is reaped + log.Errorf("write %v: %v", p, err) + p.close() + } +} + +func (s *Server) downloadBlocks(ctx context.Context) { + log.Tracef("downloadBlocks") + defer log.Tracef("downloadBlocks exit") + + now := time.Now() + + defer func() { + // if we are complete we need to kick off utxo sync + go s.utxoIndexer(ctx) + }() + + s.mtx.Lock() + defer s.mtx.Unlock() + + for k, v := range s.blocks { + if v != nil && now.After(v.expire) { + // kill peer as well since it is slow + if p := s.peers[v.peer]; p != nil && p.conn != nil { + p.conn.Close() // this will tear down peer + } + + // block expired, download block + s.blocks[k] = nil + v = nil // this will redownload the block + } + if v != nil { + // block already being downloaded and is not expired + continue + } + // unassigned slot, download block + for _, peer := range s.peers { + if peer.conn == nil { + // Not connected yet + continue + } + ch, err := chainhash.NewHashFromStr(k) + if err != nil { + // really should not happen + log.Errorf("download blocks hash: %v", err) + delete(s.blocks, k) + continue + } + + // sufficiently validated, record in cache + s.blocks[k] = &blockPeer{ + expire: time.Now().Add(37 * time.Second), // XXX make variable? + peer: peer.String(), + } + + go s.downloadBlock(ctx, peer, ch) + + break + } + } +} + +func (s *Server) syncBlocks(ctx context.Context) { + log.Tracef("syncBlocks") + defer log.Tracef("syncBlocks exit") + + // regardless of cache being full or no more missing blocks kick the + // downloader just to make sure we are making forward progress. + defer func() { + go s.downloadBlocks(ctx) + }() + + // Hold lock to fill blocks cache + s.mtx.Lock() + defer s.mtx.Unlock() + + // Deal with expired block downloads + used := s.blockPeerExpire() + want := defaultPendingBlocks - used + if want <= 0 { + return + } + + bm, err := s.db.BlocksMissing(ctx, want) + if err != nil { + log.Errorf("blocks missing: %v", err) + return + } + for k := range bm { + bi := bm[k] + hash, _ := chainhash.NewHash(bi.Hash[:]) + hashS := hash.String() + if _, ok := s.blocks[hashS]; ok { + continue + } + s.blocks[hashS] = nil // pending block + } +} + +func (s *Server) handleHeaders(ctx context.Context, p *peer, msg *wire.MsgHeaders) { + log.Tracef("handleHeaders %v", p) + defer log.Tracef("handleHeaders exit %v", p) + + log.Debugf("handleHeaders (%v): %v", p, len(msg.Headers)) + + if len(msg.Headers) == 0 { + // This may signify the end of IBD but isn't 100%. We can fart + // around with mean block time to determine if this peer is + // just behind or if we are nominally where we should be. This + // test will never be 100% accurate. + + s.mtx.Lock() + lastBH := s.lastBlockHeader.Timestamp() + s.mtx.Unlock() + if time.Now().Sub(lastBH) > 6*s.chainParams.TargetTimePerBlock { + log.Infof("peer not synced: %v", p) + return + } + + go s.syncBlocks(ctx) + + return + } + + // This code works because duplicate blockheaders are rejected later on + // but only after a somewhat expensive parameter setup and database + // call. + // + // There really is no good way of determining if we can escape the + // expensive calls so we just eat it. + + // Make sure we can connect these headers in database + dbpbh, err := s.db.BlockHeaderByHash(ctx, msg.Headers[0].PrevBlock[:]) + if err != nil { + log.Errorf("handle headers no previous block header: %v", + msg.Headers[0].BlockHash()) + return + } + pbh, err := bytes2Header(dbpbh.Header) + if err != nil { + log.Errorf("invalid block header: %v", err) + return + } + + // Construct insert list and nominally validate headers + headers := make([]tbcd.BlockHeader, 0, len(msg.Headers)) + height := dbpbh.Height + 1 + for k := range msg.Headers { + if !hashEqual(msg.Headers[k].PrevBlock, pbh.BlockHash()) { + log.Errorf("cannot connect %v at height %v", + msg.Headers[k].PrevBlock, height) + return + } + + headers = append(headers, tbcd.BlockHeader{ + Hash: sliceChainHash(msg.Headers[k].BlockHash()), + Height: height, + Header: h2b(msg.Headers[k]), + }) + + pbh = msg.Headers[k] + height++ + } + + if len(headers) > 0 { + err := s.db.BlockHeadersInsert(ctx, headers) + if err != nil { + // This ends the race between peers during IBD. + if !database.ErrDuplicate.Is(err) { + log.Errorf("block headers insert: %v", err) + } + return + } + + // If we get here try to store the last blockheader that was + // inserted. This may race so we have to take the mutex and + // check height. + lbh := headers[len(headers)-1] + + s.mtx.Lock() + if lbh.Height > s.lastBlockHeader.Height { + s.lastBlockHeader = lbh + } + s.mtx.Unlock() + + log.Infof("Inserted %v block headers height %v", + len(headers), lbh.Height) + + // Ask for next batch of headers + err = s.getHeaders(ctx, p, lbh.Header) + if err != nil { + log.Errorf("get headers: %v", err) + return + } + } +} + +func (s *Server) handleBlock(ctx context.Context, p *peer, msg *wire.MsgBlock) { + log.Tracef("handleBlock (%v)", p) + defer log.Tracef("handleBlock exit (%v)", p) + + block := btcutil.NewBlock(msg) + bhs := block.Hash().String() + bb, err := block.Bytes() // XXX we should not being doing this twice but requires a modification to the wire package + if err != nil { + log.Errorf("block bytes %v: %v", block.Hash(), err) + return + } + b := &tbcd.Block{ + Hash: sliceChainHash(*block.Hash()), + Block: bb, + } + + if s.cfg.BlockSanity { + err = blockchain.CheckBlockSanity(block, s.chainParams.PowLimit, + s.timeSource) + if err != nil { + log.Errorf("Unable to validate block hash %v: %v", bhs, err) + return + } + + // Contextual check of block + // + // We do want these checks however we download the blockchain + // out of order this we will have to do something clever for + // prevNode. + // + // header := &block.MsgBlock().Header + // flags := blockchain.BFNone + // err := blockchain.CheckBlockHeaderContext(header, prevNode, flags, bctxt, false) + // if err != nil { + // log.Errorf("Unable to validate context of block hash %v: %v", bhs, err) + // return + // } + } + + height, err := s.db.BlockInsert(ctx, b) + if err != nil { + log.Errorf("block insert %v: %v", bhs, err) + } else { + log.Infof("Insert block %v at %v txs %v %v", bhs, height, + len(msg.Transactions), msg.Header.Timestamp) + } + + // Whatever happens,, delete from cache and potentially try again + var ( + printStats bool + blocksSize uint64 + blocksInserted int + blocksDuplicate int // keep track of this until have less of them + delta time.Duration + + // blocks pending + blocksPending int + + // peers + goodPeers int + badPeers int + activePeers int + connectedPeers int + ) + s.mtx.Lock() + delete(s.blocks, bhs) // remove block from cache regardless of insert result + + // Stats + if err == nil { + s.blocksSize += uint64(len(b.Block) + len(b.Hash)) + if _, ok := s.blocksInserted[bhs]; ok { + s.blocksDuplicate++ + } else { + s.blocksInserted[bhs] = struct{}{} + } + } + now := time.Now() + if now.After(s.printTime) { + printStats = true + + blocksSize = s.blocksSize + blocksInserted = len(s.blocksInserted) + blocksDuplicate = s.blocksDuplicate + // This is super awkward but prevents calculating N inserts * + // time.Before(10*time.Second). + delta = now.Sub(s.printTime.Add(-10 * time.Second)) + + s.blocksSize = 0 + s.blocksInserted = make(map[string]struct{}, 8192) + s.blocksDuplicate = 0 + s.printTime = now.Add(10 * time.Second) + + // Grab pending block cache stats + blocksPending = len(s.blocks) + + // Grab some peer stats as well + activePeers = len(s.peers) + goodPeers, badPeers = s.db.PeersStats(ctx) + // Gonna take it right into the Danger Zone! (double mutex) + for _, peer := range s.peers { + if peer.isConnected() { + connectedPeers++ + } + } + } + s.mtx.Unlock() + + if printStats { + // XXX this counts errors somehow after ibd, probably because + // duplicate blocks are downloaded when an inv comes in. + log.Infof("Inserted %v blocks (%v, %v duplicates) in the last %v", + blocksInserted, humanize.Bytes(blocksSize), blocksDuplicate, delta) + log.Infof("Pending blocks %v/%v active peers %v connected peers %v "+ + "good peers %v bad peers %v", + blocksPending, defaultPendingBlocks, activePeers, connectedPeers, + goodPeers, badPeers) + } + + // kick cache + go s.syncBlocks(ctx) +} + +func (s *Server) insertGenesis(ctx context.Context) ([]tbcd.BlockHeader, error) { + log.Tracef("insertGenesis") + defer log.Tracef("insertGenesis exit") + + // We really should be inserting the block first but block insert + // verifies that a block header exists. + log.Infof("Inserting genesis block and header: %v", s.chainParams.GenesisHash) + gbh, err := header2Bytes(&s.chainParams.GenesisBlock.Header) + if err != nil { + return nil, fmt.Errorf("serialize genesis block header: %v", err) + } + + genesisBlockHeader := &tbcd.BlockHeader{ + Height: 0, + Hash: s.chainParams.GenesisHash[:], + Header: gbh, + } + err = s.db.BlockHeadersInsert(ctx, []tbcd.BlockHeader{*genesisBlockHeader}) + if err != nil { + return nil, fmt.Errorf("genesis block header insert: %v", err) + } + + log.Debugf("Inserting genesis block") + gb, err := btcutil.NewBlock(s.chainParams.GenesisBlock).Bytes() + if err != nil { + return nil, fmt.Errorf("genesis block encode: %v", err) + } + _, err = s.db.BlockInsert(ctx, &tbcd.Block{ + Hash: s.chainParams.GenesisHash[:], + Block: gb, + }) + if err != nil { + return nil, fmt.Errorf("genesis block insert: %v", err) + } + + return []tbcd.BlockHeader{*genesisBlockHeader}, nil +} + +// + +func (s *Server) BlockHeaderByHash(ctx context.Context, hash *chainhash.Hash) (*wire.BlockHeader, uint64, error) { + log.Tracef("BlockHeaderByHash") + defer log.Tracef("BlockHeaderByHash exit") + + bh, err := s.db.BlockHeaderByHash(ctx, hash[:]) + if err != nil { + return nil, 0, fmt.Errorf("db block header by hash: %w", err) + } + bhw, err := bytes2Header(bh.Header) + if err != nil { + return nil, 0, fmt.Errorf("bytes to header: %w", err) + } + return bhw, bh.Height, nil +} + +func (s *Server) blockHeadersByHeight(ctx context.Context, height uint64) ([]tbcd.BlockHeader, error) { + log.Tracef("blockHeadersByHeight") + defer log.Tracef("blockHeadersByHeight exit") + + bhs, err := s.db.BlockHeadersByHeight(ctx, height) + if err != nil { + return nil, fmt.Errorf("db block header by height: %w", err) + } + + return bhs, nil +} + +func (s *Server) RawBlockHeadersByHeight(ctx context.Context, height uint64) ([]api.ByteSlice, error) { + log.Tracef("RawBlockHeadersByHeight") + defer log.Tracef("RawBlockHeadersByHeight exit") + + bhs, err := s.blockHeadersByHeight(ctx, height) + if err != nil { + return nil, err + } + + var headers []api.ByteSlice + for _, bh := range bhs { + headers = append(headers, []byte(bh.Header)) + } + + return headers, nil +} + +func (s *Server) BlockHeadersByHeight(ctx context.Context, height uint64) ([]*wire.BlockHeader, error) { + log.Tracef("BlockHeadersByHeight") + defer log.Tracef("BlockHeadersByHeight exit") + + blockHeaders, err := s.blockHeadersByHeight(ctx, height) + if err != nil { + return nil, err + } + + wireBlockHeaders := make([]*wire.BlockHeader, 0, len(blockHeaders)) + for _, bh := range blockHeaders { + w, err := bh.Wire() + if err != nil { + return nil, err + } + wireBlockHeaders = append(wireBlockHeaders, w) + } + return wireBlockHeaders, nil +} + +// RawBlockHeadersBest returns the raw headers for the best known blocks. +func (s *Server) RawBlockHeadersBest(ctx context.Context) (uint64, []api.ByteSlice, error) { + log.Tracef("RawBlockHeadersBest") + defer log.Tracef("RawBlockHeadersBest exit") + + bhs, err := s.db.BlockHeadersBest(ctx) + if err != nil { + return 0, nil, err + } + + var height uint64 + if len(bhs) > 0 { + height = bhs[0].Height + } + + var headers []api.ByteSlice + for _, bh := range bhs { + headers = append(headers, []byte(bh.Header)) + } + + return height, headers, nil +} + +// BlockHeadersBest returns the headers for the best known blocks. +func (s *Server) BlockHeadersBest(ctx context.Context) (uint64, []*wire.BlockHeader, error) { + log.Tracef("BlockHeadersBest") + defer log.Tracef("BlockHeadersBest exit") + + blockHeaders, err := s.db.BlockHeadersBest(ctx) + if err != nil { + return 0, nil, err + } + + var height uint64 + if len(blockHeaders) > 0 { + height = blockHeaders[0].Height + } + + wireBlockHeaders := make([]*wire.BlockHeader, 0, len(blockHeaders)) + for _, bh := range blockHeaders { + w, err := bh.Wire() + if err != nil { + return 0, nil, err + } + wireBlockHeaders = append(wireBlockHeaders, w) + } + + return height, wireBlockHeaders, nil +} + +func (s *Server) BalanceByAddress(ctx context.Context, encodedAddress string) (uint64, error) { + addr, err := btcutil.DecodeAddress(encodedAddress, s.chainParams) + if err != nil { + return 0, err + } + + script, err := txscript.PayToAddrScript(addr) + if err != nil { + return 0, err + } + + scriptHash := sha256.Sum256(script) + + balance, err := s.db.BalanceByScriptHash(ctx, scriptHash) + if err != nil { + return 0, err + } + + return balance, nil +} + +func (s *Server) UtxosByAddress(ctx context.Context, encodedAddress string, start uint64, count uint64) ([]tbcd.Utxo, error) { + addr, err := btcutil.DecodeAddress(encodedAddress, s.chainParams) + if err != nil { + return nil, err + } + + script, err := txscript.PayToAddrScript(addr) + if err != nil { + return nil, err + } + + scriptHash := sha256.Sum256(script) + + utxos, err := s.db.UtxosByScriptHash(ctx, scriptHash, start, count) + if err != nil { + return nil, err + } + return utxos, nil +} + +func (s *Server) TxById(ctx context.Context, txId tbcd.TxId) (*wire.MsgTx, error) { + blockHashes, err := s.db.BlocksByTxId(ctx, txId) + if err != nil { + return nil, err + } + + // chain hash stores the bytes in reverse order + revTxId := bytes.Clone(txId[:]) + slices.Reverse(revTxId) + ch, err := chainhash.NewHashFromStr(hex.EncodeToString(revTxId[:])) + if err != nil { + return nil, err + } + + for _, blockHash := range blockHashes { + block, err := s.db.BlockByHash(ctx, blockHash[:]) + if err != nil { + return nil, err + } + + parsedBlock, err := btcutil.NewBlockFromBytes(block.Block) + if err != nil { + return nil, err + } + + for _, tx := range parsedBlock.Transactions() { + if tx.Hash().IsEqual(ch) { + return tx.MsgTx(), nil + } + } + } + + return nil, database.ErrNotFound +} + +func feesFromTransactions(txs []*btcutil.Tx) error { + for idx, tx := range txs { + for _, txIn := range tx.MsgTx().TxIn { + if idx == 0 { + // Skip coinbase inputs + continue + } + _ = txIn + } + for outIndex, txOut := range tx.MsgTx().TxOut { + if txscript.IsUnspendable(txOut.PkScript) { + continue + } + _ = outIndex + } + } + + return nil +} + +func (s *Server) FeesAtHeight(ctx context.Context, height, count int64) (uint64, error) { + log.Tracef("FeesAtHeight") + defer log.Tracef("FeesAtHeight exit") + + if height-count < 0 { + return 0, fmt.Errorf("height - count is less than 0") + } + var fees uint64 + for i := int64(0); i < int64(count); i++ { + log.Infof("%v", uint64(height-i)) + bhs, err := s.db.BlockHeadersByHeight(ctx, uint64(height-i)) + if err != nil { + return 0, fmt.Errorf("headers by height: %w", err) + } + if len(bhs) != 1 { + return 0, fmt.Errorf("too many block headers: %v", len(bhs)) + } + be, err := s.db.BlockByHash(ctx, bhs[0].Hash) + if err != nil { + return 0, fmt.Errorf("block by hash: %w", err) + } + b, err := btcutil.NewBlockFromBytes(be.Block) + if err != nil { + ch, _ := chainhash.NewHash(bhs[0].Hash) + return 0, fmt.Errorf("could not decode block %v %v: %v", + height, ch, err) + } + + // walk block tx' + err = feesFromTransactions(b.Transactions()) + if err != nil { + return 0, fmt.Errorf("fees from transactions %v %v: %v", + height, b.Hash(), err) + } + } + + return fees, fmt.Errorf("not yet") +} + +type SyncInfo struct { + Synced bool // True when all indexing is caught up + BlockHeaderHeight uint64 // last block header height + UtxoHeight uint64 // last indexed utxo block height + TxHeight uint64 // last indexed tx block height +} + +func (s *Server) Synced(ctx context.Context) (si SyncInfo) { + s.mtx.Lock() + defer s.mtx.Unlock() + si.BlockHeaderHeight = s.lastBlockHeader.Height + + // These values are cached in leveldb so it is ok to call with mutex + // held. + // + // Note that index heights are start indexing values thus they are off + // by one from the last block height seen. + uh, err := s.db.MetadataGet(ctx, UtxoIndexHeightKey) + if err == nil { + si.UtxoHeight = binary.BigEndian.Uint64(uh) - 1 + } + th, err := s.db.MetadataGet(ctx, TxIndexHeightKey) + if err == nil { + si.TxHeight = binary.BigEndian.Uint64(th) - 1 + } + if si.UtxoHeight == si.TxHeight && si.UtxoHeight == si.BlockHeaderHeight && + !s.blksMissing(ctx) { + si.Synced = true + } + return +} + +// DBOpen opens the underlying server database. It has been put in its own +// function to make it available during tests and hemictl. +func (s *Server) DBOpen(ctx context.Context) error { + log.Tracef("DBOpen") + defer log.Tracef("DBOpen exit") + + // This should have been verified but let's not make assumptions. + switch s.cfg.Network { + case "testnet3": + case "mainnet": + case networkLocalnet: // XXX why is this here?, this breaks the filepath.Join + default: + return fmt.Errorf("unsupported network: %v", s.cfg.Network) + } + + // Open db. + var err error + s.db, err = level.New(ctx, filepath.Join(s.cfg.LevelDBHome, s.cfg.Network)) + if err != nil { + return fmt.Errorf("open level database: %v", err) + } + + return nil +} + +func (s *Server) DBClose() error { + log.Tracef("DBClose") + defer log.Tracef("DBClose") + + return s.db.Close() +} + +func (s *Server) Run(pctx context.Context) error { + log.Tracef("Run") + defer log.Tracef("Run exit") + + if !s.testAndSetRunning(true) { + return fmt.Errorf("tbc already running") + } + defer s.testAndSetRunning(false) + + // We need a lot of open files and memory for the indexes. Best effort + // to echo to the user what the ulimits are. + if s.ignoreUlimit { + log.Warningf("ignoring ulimit requirements") + } else if ulimitSupported { + if err := verifyUlimits(); err != nil { + return fmt.Errorf("verify ulimits: %w", err) + } + } else { + log.Errorf("This architecture does not supported ulimit verification. " + + "Consult the README for minimum values.") + } + + ctx, cancel := context.WithCancel(pctx) + defer cancel() + + err := s.DBOpen(ctx) + if err != nil { + return fmt.Errorf("Failed to open level database: %w", err) + } + defer func() { + err := s.DBClose() + if err != nil { + log.Errorf("db close: %v", err) + } + }() + + // Find out where IBD is at + bhs, err := s.db.BlockHeadersBest(ctx) + if err != nil { + return fmt.Errorf("block headers best: %v", err) + } + // No entries means we are at genesis + if len(bhs) == 0 { + bhs, err = s.insertGenesis(ctx) + if err != nil { + return fmt.Errorf("insert genesis: %v", err) + } + bhs, err = s.db.BlockHeadersBest(ctx) + if err != nil { + return err + } + } else if len(bhs) > 1 { + return fmt.Errorf("blockheaders best: unsupported fork") + } + s.lastBlockHeader = bhs[0] // Prime last seen block header + log.Infof("Starting block headers sync at height: %v time %v", + bhs[0].Height, bhs[0].Timestamp()) + + // HTTP server + mux := http.NewServeMux() + log.Infof("handle (tbc): %s", tbcapi.RouteWebsocket) + mux.HandleFunc(tbcapi.RouteWebsocket, s.handleWebsocket) + + httpServer := &http.Server{ + Addr: s.cfg.ListenAddress, + Handler: mux, + BaseContext: func(_ net.Listener) context.Context { return ctx }, + } + httpErrCh := make(chan error) + go func() { + log.Infof("Listening: %s", s.cfg.ListenAddress) + httpErrCh <- httpServer.ListenAndServe() + }() + defer func() { + if err = httpServer.Shutdown(ctx); err != nil { + log.Errorf("http server exit: %v", err) + return + } + log.Infof("RPC server shutdown cleanly") + }() + + // Prometheus + if s.cfg.PrometheusListenAddress != "" { + d, err := deucalion.New(&deucalion.Config{ + ListenAddress: s.cfg.PrometheusListenAddress, + }) + if err != nil { + return fmt.Errorf("failed to create server: %w", err) + } + cs := []prometheus.Collector{ + s.cmdsProcessed, + prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Subsystem: promSubsystem, + Name: "running", + Help: "Is tbc service running.", + }, s.promRunning), + } + s.wg.Add(1) + go func() { + defer s.wg.Done() + if err := d.Run(ctx, cs); err != context.Canceled { + log.Errorf("prometheus terminated with error: %v", err) + return + } + log.Infof("prometheus clean shutdown") + }() + } + + errC := make(chan error) + s.wg.Add(1) + go func() { + defer s.wg.Done() + err := s.startPeerManager(ctx) + if err != nil { + select { + case errC <- err: + default: + } + } + }() + + select { + case <-ctx.Done(): + err = ctx.Err() + case err = <-errC: + case err = <-httpErrCh: + } + cancel() + + log.Infof("tbc service shutting down") + s.wg.Wait() + log.Infof("tbc service clean shutdown") + + return err +} diff --git a/service/tbc/tbc_test.go b/service/tbc/tbc_test.go new file mode 100644 index 000000000000..349d0c9da18b --- /dev/null +++ b/service/tbc/tbc_test.go @@ -0,0 +1,2150 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tbc + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "os" + "slices" + "strconv" + "strings" + "testing" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" + "github.com/go-test/deep" + "github.com/phayes/freeport" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + "nhooyr.io/websocket" + "nhooyr.io/websocket/wsjson" + + "github.com/hemilabs/heminetwork/api" + "github.com/hemilabs/heminetwork/api/protocol" + "github.com/hemilabs/heminetwork/api/tbcapi" + "github.com/hemilabs/heminetwork/bitcoin" + "github.com/hemilabs/heminetwork/database/tbcd" +) + +const ( + privateKey = "72a2c41c84147325ce3c0f37697ef1e670c7169063dda89be9995c3c5219740f" + levelDbHome = ".testleveldb" +) + +type StdoutLogConsumer struct { + Name string // name of service +} + +func (t *StdoutLogConsumer) Accept(l testcontainers.Log) { + fmt.Printf("%s: %s", t.Name, string(l.Content)) +} + +func skipIfNoDocker(t *testing.T) { + envValue := os.Getenv("HEMI_DOCKER_TESTS") + val, err := strconv.ParseBool(envValue) + if envValue != "" && err != nil { + t.Fatal(err) + } + + if !val { + t.Skip("skipping docker tests") + } +} + +func TestBlockHeadersByHeightRaw(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 100, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + _, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BlockHeadersByHeightRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BlockHeadersByHeightRawRequest{ + Height: 55, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBlockHeadersByHeightRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + } + + if lastErr != nil { + t.Fatal(lastErr) + } + + bh, err := bytes2Header(response.BlockHeaders[0]) + if err != nil { + t.Fatal(err) + } + + t.Logf(spew.Sdump(bh)) + + if response.Error != nil { + t.Errorf("got unwanted error: %v", response.Error) + } + + cliBlockHeader := bitcoindBlockAtHeight(ctx, t, bitcoindContainer, 55) + expected := cliBlockHeaderToRaw(t, cliBlockHeader) + if diff := deep.Equal(expected, response.BlockHeaders); len(diff) > 0 { + t.Errorf("unexpected diff: %s", diff) + } +} + +func TestBlockHeadersByHeight(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 100, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BlockHeadersByHeightResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BlockHeadersByHeightRequest{ + Height: 55, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBlockHeadersByHeightResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + + if response.Error != nil { + t.Errorf("got unwanted error: %v", response.Error) + } + + cliBlockHeader := bitcoindBlockAtHeight(ctx, t, bitcoindContainer, 55) + expected := cliBlockHeaderToTBC(t, cliBlockHeader) + if diff := deep.Equal(expected, response.BlockHeaders); len(diff) > 0 { + t.Errorf("unexpected diff: %s", diff) + } +} + +func TestBlockHeadersByHeightDoesNotExist(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 100, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BlockHeadersByHeightResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BlockHeadersByHeightRequest{ + Height: 550, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBlockHeadersByHeightResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + + if response.Error.Message != "block headers not found at height 550" { + t.Fatalf("unexpected error message: %s", response.Error.Message) + } +} + +func TestBlockHeadersBestRaw(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 50, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BlockHeadersBestRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BlockHeadersBestRawRequest{}) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBlockHeadersBestRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + } + + if lastErr != nil { + t.Fatal(lastErr) + } + + bh, err := bytes2Header(response.BlockHeaders[0]) + if err != nil { + t.Fatal(err) + } + + t.Logf(spew.Sdump(bh)) + + if response.Error != nil { + t.Errorf("got unwanted error: %v", response.Error) + } + + cliBlockHeader := bitcoindBestBlock(ctx, t, bitcoindContainer) + expected := cliBlockHeaderToRaw(t, cliBlockHeader) + if diff := deep.Equal(expected, response.BlockHeaders); len(diff) > 0 { + t.Errorf("unexpected diff: %s", diff) + } +} + +func TestBtcBlockHeadersBest(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 100, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BlockHeadersBestResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BlockHeadersBestRequest{}) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBlockHeadersBestResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + + if response.Error != nil { + t.Errorf("got unwanted error: %v", response.Error) + } + + cliBlockHeader := bitcoindBestBlock(ctx, t, bitcoindContainer) + expected := cliBlockHeaderToTBC(t, cliBlockHeader) + if diff := deep.Equal(expected, response.BlockHeaders); len(diff) > 0 { + t.Errorf("unexpected diff: %s", diff) + } +} + +func TestServerBlockHeadersBest(t *testing.T) { + skipIfNoDocker(t) + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + blocks := uint64(100) + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, blocks, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + tbcServer, _ := createTbcServer(ctx, t, mappedPeerPort) + + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + + height, bhs, err := tbcServer.BlockHeadersBest(ctx) + if err != nil { + t.Errorf("BlockHeadersBest() err = %v, want nil", err) + } + + if l := len(bhs); l != 1 { + t.Errorf("BlockHeadersBest() block len = %d, want 1", l) + } + + if height != blocks { + t.Errorf("BlockHeadersBest() height = %d, want %d", height, blocks) + } +} + +func TestBalanceByAddress(t *testing.T) { + skipIfNoDocker(t) + + type testTableItem struct { + name string + address func() string + doNotGenerate bool + } + + testTable := []testTableItem{ + { + name: "Pay to public key hash", + address: func() string { + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + }, + { + name: "Pay to script hash", + address: func() string { + address, err := btcutil.NewAddressScriptHash([]byte("blahblahscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + }, + { + name: "Pay to witness public key hash", + address: func() string { + address, err := btcutil.NewAddressWitnessPubKeyHash([]byte("blahblahwitnesspublickeyhash")[:20], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + }, + { + name: "Pay to witness script hash", + address: func() string { + address, err := btcutil.NewAddressWitnessScriptHash([]byte("blahblahwitnessscripthashblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + }, + { + name: "Pay to taproot", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + }, + { + name: "no balance", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + doNotGenerate: true, + }, + } + + for _, tti := range testTable { + t.Run(tti.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + initialBlocks := 0 + if !tti.doNotGenerate { + initialBlocks = 4 + } + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, uint64(initialBlocks), tti.address()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + // generate to another address to ensure it's not included in our query + someOtherAddress, err := btcutil.NewAddressScriptHash([]byte("blahblahotherscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + "3", + someOtherAddress.EncodeAddress(), + }) + if err != nil { + t.Fatal(err) + } + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.BalanceByAddressResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.UtxoIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.BalanceByAddressRequest{ + Address: tti.address(), + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdBalanceByAddressResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + var pricePerBlock uint64 = 50 * 100000000 + var blocks uint64 = 4 + var expectedBalance uint64 = 0 + if !tti.doNotGenerate { + expectedBalance = pricePerBlock * blocks + } + + expected := tbcapi.BalanceByAddressResponse{ + Balance: expectedBalance, + Error: nil, + } + if diff := deep.Equal(expected, response); len(diff) > 0 { + if response.Error != nil { + t.Error(response.Error.Message) + } + t.Logf("unexpected diff: %s", diff) + + // there is a chance we just haven't finished indexing + // the blocks and txs, retry until timeout + continue + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + }) + } +} + +func TestUtxosByAddressRaw(t *testing.T) { + skipIfNoDocker(t) + + type testTableItem struct { + name string + address func() string + doNotGenerate bool + limit uint64 + start uint64 + } + + testTable := []testTableItem{ + { + name: "Pay to public key hash", + address: func() string { + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to script hash", + address: func() string { + address, err := btcutil.NewAddressScriptHash([]byte("blahblahscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to witness public key hash", + address: func() string { + address, err := btcutil.NewAddressWitnessPubKeyHash([]byte("blahblahwitnesspublickeyhash")[:20], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to witness script hash", + address: func() string { + address, err := btcutil.NewAddressWitnessScriptHash([]byte("blahblahwitnessscripthashblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to taproot", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "no balance", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + doNotGenerate: true, + limit: 10, + }, + { + name: "small limit", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblahsmalllimit")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 2, + }, + { + name: "offset", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblahsmalllimit")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + start: 3, + limit: 10, + }, + } + + for _, tti := range testTable { + t.Run(tti.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + var bitcoindContainer testcontainers.Container + var mappedPeerPort nat.Port + initialBlocks := 0 + if !tti.doNotGenerate { + initialBlocks = 4 + } + bitcoindContainer, mappedPeerPort = createBitcoindWithInitialBlocks(ctx, t, uint64(initialBlocks), tti.address()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + // generate to another address to ensure it's not included in our query + someOtherAddress, err := btcutil.NewAddressScriptHash([]byte("blahblahotherscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + "3", + someOtherAddress.EncodeAddress(), + }) + if err != nil { + t.Fatal(err) + } + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.UtxosByAddressRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.UtxoIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.UtxosByAddressRawRequest{ + Address: tti.address(), + Start: uint(tti.start), + Count: uint(tti.limit), + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdUtxosByAddressRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + // we generated 4 blocks to this address previously, therefore + // there should be 4 utxos + expectedCount := 4 - tti.start + if tti.limit < uint64(expectedCount) { + expectedCount = tti.limit + } + + if !tti.doNotGenerate && len(response.Utxos) != int(expectedCount) { + t.Fatalf("should have %d utxos, received: %d", expectedCount, len(response.Utxos)) + } else if tti.doNotGenerate && len(response.Utxos) != 0 { + t.Fatalf("did not generate any blocks for address, should not have utxos") + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + }) + } +} + +func TestUtxosByAddress(t *testing.T) { + skipIfNoDocker(t) + + type testTableItem struct { + name string + address func() string + doNotGenerate bool + limit uint64 + start uint64 + } + + testTable := []testTableItem{ + { + name: "Pay to public key hash", + address: func() string { + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to script hash", + address: func() string { + address, err := btcutil.NewAddressScriptHash([]byte("blahblahscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to witness public key hash", + address: func() string { + address, err := btcutil.NewAddressWitnessPubKeyHash([]byte("blahblahwitnesspublickeyhash")[:20], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to witness script hash", + address: func() string { + address, err := btcutil.NewAddressWitnessScriptHash([]byte("blahblahwitnessscripthashblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "Pay to taproot", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 10, + }, + { + name: "no balance", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblah")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + doNotGenerate: true, + limit: 10, + }, + { + name: "small limit", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblahsmalllimit")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + limit: 2, + }, + { + name: "offset", + address: func() string { + address, err := btcutil.NewAddressTaproot([]byte("blahblahwtaprootblahblahblahblahsmalllimit")[:32], &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + + return address.EncodeAddress() + }, + start: 3, + limit: 10, + }, + } + + for _, tti := range testTable { + t.Run(tti.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + var bitcoindContainer testcontainers.Container + var mappedPeerPort nat.Port + initialBlocks := 0 + if !tti.doNotGenerate { + initialBlocks = 4 + } + bitcoindContainer, mappedPeerPort = createBitcoindWithInitialBlocks(ctx, t, uint64(initialBlocks), tti.address()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + // generate to another address to ensure it's not included in our query + someOtherAddress, err := btcutil.NewAddressScriptHash([]byte("blahblahotherscripthash"), &chaincfg.RegressionNetParams) + if err != nil { + t.Fatal(err) + } + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + "3", + someOtherAddress.EncodeAddress(), + }) + if err != nil { + t.Fatal(err) + } + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.UtxosByAddressResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.UtxoIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.UtxosByAddressRequest{ + Address: tti.address(), + Start: uint(tti.start), + Count: uint(tti.limit), + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdUtxosByAddressResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + // we generated 4 blocks to this address previously, therefore + // there should be 4 utxos + expectedCount := 4 - tti.start + if tti.limit < uint64(expectedCount) { + expectedCount = tti.limit + } + + if !tti.doNotGenerate && len(response.Utxos) != int(expectedCount) { + t.Fatalf("should have %d utxos, received: %d", expectedCount, len(response.Utxos)) + } else if tti.doNotGenerate && len(response.Utxos) != 0 { + t.Fatalf("did not generate any blocks for address, should not have utxos") + } + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } + }) + } +} + +func TestTxByIdRaw(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 4, address.String()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRawRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error != nil { + t.Fatal(response.Error.Message) + } + + // XXX - write a better test than this, we should be able to compare + // against bitcoin-cli response fields + + // did we get the tx and can we parse it? + tx, err := bytes2Tx(response.Tx) + if err != nil { + t.Fatal(err) + } + + // is the hash equal to what we queried for? + if tx.TxHash().String() != txId { + t.Fatalf("id mismatch: %s != %s", tx.TxHash().String(), txId) + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func TestTxByIdRawInvalid(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 4, address.String()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + txIdBytes[0]++ + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRawRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error == nil { + t.Fatal("expecting error") + } + + if response.Error != nil { + if !strings.Contains(response.Error.Message, "not found:") { + t.Fatalf("incorrect error found %s", response.Error.Message) + } + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func TestTxByIdRawNotFound(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 0, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + "4", + address.EncodeAddress(), + }) + if err != nil { + t.Fatal(err) + } + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdRawResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + txIdBytes = append(txIdBytes, 8) + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRawRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdRawResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error == nil { + t.Fatal("expecting error") + } + + if response.Error != nil { + if !strings.Contains(response.Error.Message, "invalid tx id") { + t.Fatalf("incorrect error found: %s", response.Error.Message) + } + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func TestTxById(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 4, address.String()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error != nil { + t.Fatal(response.Error.Message) + } + + tx, err := tbcServer.TxById(ctx, tbcd.TxId(txIdBytes)) + if err != nil { + t.Fatal(err) + } + + w := wireTxToTbcapiTx(tx) + + if diff := deep.Equal(w, &response.Tx); len(diff) > 0 { + t.Fatal(diff) + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func TestTxByIdInvalid(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 4, address.String()) + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + txIdBytes[0]++ + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error == nil { + t.Fatal("expecting error") + } + + if response.Error != nil { + if !strings.Contains(response.Error.Message, "not found:") { + t.Fatalf("incorrect error found %s", response.Error.Message) + } + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func TestTxByIdNotFound(t *testing.T) { + skipIfNoDocker(t) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) + defer cancel() + bitcoindContainer, mappedPeerPort := createBitcoindWithInitialBlocks(ctx, t, 0, "") + defer func() { + if err := bitcoindContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + _, _, address, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + "4", + address.EncodeAddress(), + }) + if err != nil { + t.Fatal(err) + } + + tbcServer, tbcUrl := createTbcServer(ctx, t, mappedPeerPort) + + c, _, err := websocket.Dial(ctx, tbcUrl, nil) + if err != nil { + t.Fatal(err) + } + defer c.CloseNow() + + assertPing(ctx, t, c, tbcapi.CmdPingRequest) + + tws := &tbcWs{ + conn: protocol.NewWSConn(c), + } + + var lastErr error + var response tbcapi.TxByIdResponse + for { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + err = tbcServer.TxIndexer(ctx, 0, 1000) + if err != nil { + t.Fatal(err) + } + lastErr = nil + txId := getRandomTxId(ctx, t, bitcoindContainer) + txIdBytes, err := hex.DecodeString(txId) + if err != nil { + t.Fatal(err) + } + + txIdBytes = append(txIdBytes, 8) + + slices.Reverse(txIdBytes) + + err = tbcapi.Write(ctx, tws.conn, "someid", tbcapi.TxByIdRequest{ + TxId: txIdBytes, + }) + if err != nil { + lastErr = err + continue + } + + var v protocol.Message + err = wsjson.Read(ctx, c, &v) + if err != nil { + lastErr = err + continue + } + + if v.Header.Command == tbcapi.CmdTxByIdResponse { + if err := json.Unmarshal(v.Payload, &response); err != nil { + t.Fatal(err) + } + + if response.Error == nil { + t.Fatal("expecting error") + } + + if response.Error != nil { + if !strings.Contains(response.Error.Message, "invalid tx id") { + t.Fatalf("incorrect error found: %s", response.Error.Message) + } + } + + break + } else { + lastErr = fmt.Errorf("received unexpected command: %s", v.Header.Command) + } + + } + + if lastErr != nil { + t.Fatal(lastErr) + } +} + +func createBitcoind(ctx context.Context, t *testing.T) testcontainers.Container { + id, err := randHexId(6) + if err != nil { + t.Fatal("failed to generate random id:", err) + } + + name := fmt.Sprintf("bitcoind-%s", id) + req := testcontainers.ContainerRequest{ + Image: "kylemanna/bitcoind", + Cmd: []string{"bitcoind", "-regtest=1", "-debug=1", "-rpcallowip=0.0.0.0/0", "-rpcbind=0.0.0.0:18443", "-txindex=1", "-noonion", "-listenonion=0"}, + ExposedPorts: []string{"18443", "18444"}, + WaitingFor: wait.ForLog("dnsseed thread exit").WithPollInterval(1 * time.Second), + LogConsumerCfg: &testcontainers.LogConsumerConfig{ + Consumers: []testcontainers.LogConsumer{&StdoutLogConsumer{ + Name: name, + }}, + }, + Name: name, + HostConfigModifier: func(hostConfig *container.HostConfig) { + hostConfig.PortBindings = nat.PortMap{ + "18443/tcp": []nat.PortBinding{ + { + HostPort: "18443", + }, + }, + "18444/tcp": []nat.PortBinding{ + { + HostPort: "18444", + }, + }, + } + }, + } + bitcoindContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + return bitcoindContainer +} + +func runBitcoinCommand(ctx context.Context, t *testing.T, bitcoindContainer testcontainers.Container, cmd []string) (string, error) { + exitCode, result, err := bitcoindContainer.Exec(ctx, cmd) + if err != nil { + return "", err + } + + buf := new(strings.Builder) + _, err = io.Copy(buf, result) + if err != nil { + return "", err + } + t.Logf(buf.String()) + + if exitCode != 0 { + return "", fmt.Errorf("error code received: %d", exitCode) + } + + // first 8 bytes are header, there is also a newline character at the end of the response + return buf.String()[8 : len(buf.String())-1], nil +} + +func getRandomTxId(ctx context.Context, t *testing.T, bitcoindContainer testcontainers.Container) string { + blockHash, err := runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "getblockhash", + fmt.Sprintf("%d", 1), + }) + if err != nil { + t.Fatal(err) + } + + blockJson, err := runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "getblock", + blockHash, + }) + if err != nil { + t.Fatal(err) + } + + var parsed struct { + Tx []string `json:"tx"` + } + if err := json.Unmarshal([]byte(blockJson), &parsed); err != nil { + t.Fatal(err) + } + + if len(parsed.Tx) == 0 { + t.Fatal("was expecting at least 1 transaction") + } + + return parsed.Tx[0] +} + +func getEndpointWithRetries(ctx context.Context, container testcontainers.Container, retries int) (string, error) { + backoff := 500 * time.Millisecond + var lastError error + for i := 0; i < retries; i++ { + endpoint, err := container.Endpoint(ctx, "") + if err != nil { + lastError = err + time.Sleep(backoff) + backoff = backoff * 2 + continue + } + return endpoint, nil + } + + return "", lastError +} + +func nextPort() int { + ports, err := freeport.GetFreePorts(1000) + if err != nil && err != context.Canceled { + panic(err) + } + + return ports[time.Now().Unix()%int64(len(ports))] +} + +func createTbcServer(ctx context.Context, t *testing.T, mappedPeerPort nat.Port) (*Server, string) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + home := fmt.Sprintf("%s/%s", wd, levelDbHome) + + if err := os.RemoveAll(home); err != nil { + t.Fatal(err) + } + tcbListenAddress := fmt.Sprintf(":%d", nextPort()) + + cfg := NewDefaultConfig() + cfg.LevelDBHome = home + cfg.Network = networkLocalnet + cfg.RegtestPort = mappedPeerPort.Port() + cfg.ListenAddress = tcbListenAddress + tbcServer, err := NewServer(cfg) + if err != nil { + t.Fatal(err) + } + + tbcServer.ignoreUlimit = true + + go func() { + err := tbcServer.Run(ctx) + if err != nil && err != context.Canceled { + panic(err) + } + }() + + // let tbc index + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + + tbcUrl := fmt.Sprintf("http://localhost%s%s", tcbListenAddress, tbcapi.RouteWebsocket) + err = EnsureCanConnect(t, tbcUrl, 5*time.Second) + if err != nil { + t.Fatalf("could not connect to %s: %s", tbcUrl, err.Error()) + } + + return tbcServer, tbcUrl +} + +func EnsureCanConnect(t *testing.T, url string, timeout time.Duration) error { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + t.Logf("connecting to %s", url) + + var err error + + doneCh := make(chan bool) + go func() { + for { + c, _, err := websocket.Dial(ctx, url, nil) + if err != nil { + time.Sleep(1 * time.Second) + continue + } + c.CloseNow() + doneCh <- true + } + }() + + select { + case <-doneCh: + case <-ctx.Done(): + return fmt.Errorf("timed out trying to reach WS server in tests, last error: %s", err) + } + + return nil +} + +func assertPing(ctx context.Context, t *testing.T, c *websocket.Conn, cmd protocol.Command) { + var v protocol.Message + err := wsjson.Read(ctx, c, &v) + if err != nil { + t.Fatal(err) + } + + if v.Header.Command != cmd { + t.Fatalf("unexpected command: %s", v.Header.Command) + } +} + +// BtcCliBlockHeader represents the block header structure used by bitcoin-cli. +type BtcCliBlockHeader struct { + Hash string `json:"hash"` + Confirmations int `json:"confirmations"` + Height uint32 `json:"height"` + Version uint64 `json:"version"` + VersionHex string `json:"versionHex"` + MerkleRoot string `json:"merkleroot"` + Time uint64 `json:"time"` + MedianTime uint64 `json:"mediantime"` + Nonce uint64 `json:"nonce"` + Bits string `json:"bits"` + Difficulty float64 `json:"difficulty"` + Chainwork string `json:"chainwork"` + NTx uint64 `json:"nTx"` + PreviousBlockHash string `json:"previousblockhash"` + NextBlockHash string `json:"nextblockhash"` +} + +// cliBlockHeaderToWire converts a bitcoin-cli block header to the +// [wire.BlockHeader] representation of the block header. +func cliBlockHeaderToWire(t *testing.T, header *BtcCliBlockHeader) *wire.BlockHeader { + prevBlockHash, err := chainhash.NewHashFromStr(header.PreviousBlockHash) + if err != nil { + t.Fatal(fmt.Errorf("convert prevBlockHash to chainhash: %w", err)) + } + merkleRoot, err := chainhash.NewHashFromStr(header.MerkleRoot) + if err != nil { + t.Fatal(fmt.Errorf("convert merkleRoot to chainhash: %w", err)) + } + bits, err := strconv.ParseUint(header.Bits, 16, 64) + if err != nil { + t.Fatal(fmt.Errorf("parse bits as uint: %w", err)) + } + + blockHeader := wire.NewBlockHeader( + int32(header.Version), + prevBlockHash, + merkleRoot, + uint32(bits), + uint32(header.Nonce), + ) + blockHeader.Timestamp = time.Unix(int64(header.Time), 0) + return blockHeader +} + +// cliBlockHeaderToRaw converts a bitcoin-cli block header to a slice containing +// the raw byte representation of the block header. +func cliBlockHeaderToRaw(t *testing.T, cliBlockHeader *BtcCliBlockHeader) []api.ByteSlice { + blockHeader := cliBlockHeaderToWire(t, cliBlockHeader) + t.Logf(spew.Sdump(blockHeader)) + + bytes, err := header2Bytes(blockHeader) + if err != nil { + t.Fatal(fmt.Errorf("header to bytes: %w", err)) + } + + return []api.ByteSlice{bytes} +} + +// cliBlockHeaderToTBC converts a bitcoin-cli block header to a slice containing +// the [tbcapi.BlockHeader] representation of the block header. +func cliBlockHeaderToTBC(t *testing.T, btcCliBlockHeader *BtcCliBlockHeader) []*tbcapi.BlockHeader { + blockHeader := cliBlockHeaderToWire(t, btcCliBlockHeader) + t.Logf(spew.Sdump(blockHeader)) + return wireBlockHeadersToTBC([]*wire.BlockHeader{blockHeader}) +} + +func bitcoindBlockAtHeight(ctx context.Context, t *testing.T, bitcoindContainer testcontainers.Container, height uint64) *BtcCliBlockHeader { + blockHash, err := runBitcoinCommand(ctx, t, bitcoindContainer, []string{ + "bitcoin-cli", + "-regtest=1", + "getblockhash", + fmt.Sprintf("%d", height), + }) + if err != nil { + t.Fatal(fmt.Errorf("bitcoin-cli getblockhash %d: %w", height, err)) + } + + return bitcoindBlockByHash(ctx, t, bitcoindContainer, blockHash) +} + +func bitcoindBestBlock(ctx context.Context, t *testing.T, bitcoindContainer testcontainers.Container) *BtcCliBlockHeader { + blockHash, err := runBitcoinCommand(ctx, t, bitcoindContainer, []string{ + "bitcoin-cli", + "-regtest=1", + "getbestblockhash", + }) + if err != nil { + t.Fatal(fmt.Errorf("bitcoin-cli getbestblockhash: %w", err)) + } + + return bitcoindBlockByHash(ctx, t, bitcoindContainer, blockHash) +} + +func bitcoindBlockByHash(ctx context.Context, t *testing.T, bitcoindContainer testcontainers.Container, blockHash string) *BtcCliBlockHeader { + blockHeaderJson, err := runBitcoinCommand( + ctx, t, bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "getblockheader", + blockHash, + }) + if err != nil { + t.Fatal(fmt.Errorf("bitcoin-cli getblockheader: %w", err)) + } + + var btcCliBlockHeader BtcCliBlockHeader + if err = json.Unmarshal([]byte(blockHeaderJson), &btcCliBlockHeader); err != nil { + t.Fatal(fmt.Errorf("unmarshal json output: %w", err)) + } + + return &btcCliBlockHeader +} + +func createBitcoindWithInitialBlocks(ctx context.Context, t *testing.T, blocks uint64, overrideAddress string) (testcontainers.Container, nat.Port) { + t.Helper() + + bitcoindContainer := createBitcoind(ctx, t) + + _, _, btcAddress, err := bitcoin.KeysAndAddressFromHexString( + privateKey, + &chaincfg.RegressionNetParams, + ) + if err != nil { + t.Fatal(err) + } + + var address string + if overrideAddress != "" { + address = overrideAddress + } else { + address = btcAddress.EncodeAddress() + } + + _, err = runBitcoinCommand( + ctx, + t, + bitcoindContainer, + []string{ + "bitcoin-cli", + "-regtest=1", + "generatetoaddress", + strconv.FormatUint(blocks, 10), + address, + }) + if err != nil { + t.Fatal(err) + } + + return bitcoindContainer, nat.Port(localnetPort) +} diff --git a/service/tbc/ulimit_darwin.go b/service/tbc/ulimit_darwin.go new file mode 100644 index 000000000000..8889dc0bcd58 --- /dev/null +++ b/service/tbc/ulimit_darwin.go @@ -0,0 +1,65 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +//go:build darwin + +package tbc + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +var ( + resources = []int{ + unix.RLIMIT_AS, + unix.RLIMIT_MEMLOCK, + unix.RLIMIT_NOFILE, + unix.RLIMIT_NPROC, + } + resourceName = map[int]string{ + unix.RLIMIT_AS: "memory", + unix.RLIMIT_MEMLOCK: "lockedmem", + unix.RLIMIT_NOFILE: "nofiles", + unix.RLIMIT_NPROC: "processes", + } + resourceWant = map[int]unix.Rlimit{ + unix.RLIMIT_AS: {Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY}, + unix.RLIMIT_MEMLOCK: {Cur: 775258112, Max: 775258112}, + unix.RLIMIT_NOFILE: {Cur: 16384, Max: 16384}, + unix.RLIMIT_NPROC: {Cur: 2666, Max: 2666}, + } +) + +const ulimitSupported = true + +func verifyUlimits() error { + var p int + for k, resource := range resources { + var limit unix.Rlimit + if err := unix.Getrlimit(resource, &limit); err != nil { + return fmt.Errorf("ulimit %v: %w", k, err) + } + + // Make sure it is a reasonable value + limitRequired := resourceWant[resource] + if limitRequired.Cur > limit.Cur || limitRequired.Max > limit.Max { + return fmt.Errorf("ulimit %v: limit too low got %v, need %v", + resourceName[resource], limit.Max, limitRequired.Max) + } + + // Echo to user + if err := unix.Getrlimit(resource, &limit); err != nil { + return fmt.Errorf("ulimit %v: %w", k, err) + } + if p == 0 { + log.Infof("%-16v %-22v %-22v", "set resource", "current", "minumum") + p++ + } + log.Infof("%-16v: %-22v %-22v", resourceName[resource], limit.Cur, + limitRequired.Max) + } + return nil +} diff --git a/service/tbc/ulimit_linux.go b/service/tbc/ulimit_linux.go new file mode 100644 index 000000000000..5b04144939f8 --- /dev/null +++ b/service/tbc/ulimit_linux.go @@ -0,0 +1,69 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +//go:build linux + +package tbc + +import ( + "fmt" + "math" + + "golang.org/x/sys/unix" +) + +var ( + resources = []int{ + unix.RLIMIT_AS, + unix.RLIMIT_MEMLOCK, + unix.RLIMIT_NOFILE, + unix.RLIMIT_NPROC, + unix.RLIMIT_RSS, + } + resourceName = map[int]string{ + unix.RLIMIT_AS: "memory", + unix.RLIMIT_MEMLOCK: "lockedmem", + unix.RLIMIT_NOFILE: "nofiles", + unix.RLIMIT_NPROC: "processes", + unix.RLIMIT_RSS: "rss", + } + resourceWant = map[int]unix.Rlimit{ + unix.RLIMIT_AS: {Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY}, + unix.RLIMIT_MEMLOCK: {Cur: 775258112, Max: 775258112}, + unix.RLIMIT_NOFILE: {Cur: 16384, Max: 16384}, + unix.RLIMIT_NPROC: {Cur: 4196, Max: 4196}, + unix.RLIMIT_RSS: {Cur: math.MaxUint64, Max: math.MaxUint64}, + } +) + +const ulimitSupported = true + +func verifyUlimits() error { + var p int + for k, resource := range resources { + var limit unix.Rlimit + if err := unix.Getrlimit(resource, &limit); err != nil { + return fmt.Errorf("ulimit %v: %w", k, err) + } + + // Make sure it is a reasonable value + limitRequired := resourceWant[resource] + if limitRequired.Cur > limit.Cur || limitRequired.Max > limit.Max { + return fmt.Errorf("ulimit %v: limit too low got %v, need %v", + resourceName[resource], limit.Max, limitRequired.Max) + } + + // Echo to user + if err := unix.Getrlimit(resource, &limit); err != nil { + return fmt.Errorf("ulimit %v: %w", k, err) + } + if p == 0 { + log.Infof("%-16v %-22v %-22v", "set resource", "current", "minumum") + p++ + } + log.Infof("%-16v: %-22v %-22v", resourceName[resource], limit.Cur, + limitRequired.Max) + } + return nil +} diff --git a/service/tbc/ulimit_other.go b/service/tbc/ulimit_other.go new file mode 100644 index 000000000000..ecafcd1d20ba --- /dev/null +++ b/service/tbc/ulimit_other.go @@ -0,0 +1,13 @@ +// Copyright (c) 2024 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +//go:build !linux && !darwin + +package tbc + +const ulimitSupported = false + +func verifyUlimits() error { + return nil +} diff --git a/web/popminer/popminer.go b/web/popminer/popminer.go index d5dfb1f672be..d3f66ff55cf4 100644 --- a/web/popminer/popminer.go +++ b/web/popminer/popminer.go @@ -10,6 +10,7 @@ import ( "context" "encoding/hex" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -85,7 +86,7 @@ func generateKey(this js.Value, args []js.Value) (any, error) { } privKey, err := dcrsecpk256k1.GeneratePrivateKey() if err != nil { - return nil, fmt.Errorf("failed to generate secp256k1 private key: %v", err) + return nil, fmt.Errorf("failed to generate secp256k1 private key: %w", err) } btcAddress, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), btcChainParams) @@ -152,7 +153,7 @@ func runPopMiner(this js.Value, args []js.Value) (any, error) { pm.miner, err = popm.NewMiner(cfg) if err != nil { globalMtx.Unlock() - return nil, fmt.Errorf("Failed to create POP miner: %v", err) + return nil, fmt.Errorf("failed to create POP miner: %w", err) } globalMtx.Unlock() @@ -160,7 +161,7 @@ func runPopMiner(this js.Value, args []js.Value) (any, error) { pm.wg.Add(1) go func() { defer pm.wg.Done() - if err := pm.miner.Run(pm.ctx); err != context.Canceled { + if err := pm.miner.Run(pm.ctx); !errors.Is(err, context.Canceled) { globalMtx.Lock() defer globalMtx.Unlock() pm.err = err // Theoretically this can logic race unless we unset om diff --git a/web/www/index.html b/web/www/index.html index fef768131807..4e32a23e5b1d 100644 --- a/web/www/index.html +++ b/web/www/index.html @@ -1,3 +1,9 @@ + + diff --git a/web/www/index.js b/web/www/index.js index 396eb8d0e5ef..b39cd9f0a871 100644 --- a/web/www/index.js +++ b/web/www/index.js @@ -1,3 +1,9 @@ +/** + * Copyright (c) 2024 Hemi Labs, Inc. + * Use of this source code is governed by the MIT License, + * which can be found in the LICENSE file. + */ + // wasm ping const WASMPingShow = document.querySelector('.WASMPingShow'); diff --git a/web/www/popminer.js b/web/www/popminer.js index 85ae0ac13d39..e4917eab1668 100644 --- a/web/www/popminer.js +++ b/web/www/popminer.js @@ -1,3 +1,9 @@ +/** + * Copyright (c) 2024 Hemi Labs, Inc. + * Use of this source code is governed by the MIT License, + * which can be found in the LICENSE file. + */ + // Launch go runtime if (!WebAssembly.instantiateStreaming) { // polyfill WebAssembly.instantiateStreaming = async (resp, importObject) => {